更新时间: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>