且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

您如何监听/检测输入值的更改 - 当输入值通过 javascript 更改时?

更新时间:2022-03-29 09:13:59

.value attribute 只会在脚本编写者调用了 setAttribute('value' 来设置新值,这是一件很奇怪的事情.在几乎所有情况下,我希望通过直接分配给 value 属性来设置值,例如:

The .value attribute will only change if the script-writer has called setAttribute('value' to set the new value, which is quite an odd thing to do. In almost all situations, I would expect the value to be set by assigning to the value property directly, eg:

input.value = 'foo';

调用 setAttribute 确实会显示被检查的 DOM attribute 的变化,例如:

Calling setAttribute will indeed show a change in the inspected DOM attribute, eg:

<input value="somevalue">

const input = document.querySelector('input');
input.setAttribute('value', 'foo');
console.log(input.outerHTML);

<input>

但是仅仅分配给元素的 .value property 不会导致这样的变化:

But just assigning to the .value property of the element will not result in such a change:

const input = document.querySelector('input');
input.value = 'foo';
console.log(input.outerHTML);

<input>

分配给 .value 实际上会调用 HTMLInputElement.prototype 上的 setter 函数:

Assigning to the .value actually invokes a setter function on HTMLInputElement.prototype:

console.log(HTMLInputElement.prototype.hasOwnProperty('value'));

您可以通过将 value 的 getter/setter 直接放在元素本身上来隐藏这一点,使用 setter 调用您自己的函数,允许您侦听更改:

You can shadow this by putting a getter/setter for value directly on the element itself, with the setter invoking your own function, allowing you to listen for changes:

const { get, set } = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
const input = document.querySelector('input');
Object.defineProperty(input, 'value', {
  get() {
    return get.call(this);
  },
  set(newVal) {
    console.log('New value assigned to input: ' + newVal);
    return set.call(this, newVal);
  }
});


// example of autocomplete trying to change the input value:
input.value = 'foo';

<input>