是否有一种标准方法可以捕获 HTML 输入元素值的所有更改,无论它是由用户输入更改还是以编程方式更改?
考虑以下代码(纯粹出于示例目的,并未采用良好的编码实践编写,您可以将其视为恰好能够在某些网络浏览器中运行的伪代码:P)
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
<script>
window.onload = () => {
var test = document.getElementById("test");
test.onchange = () => {
console.log("OnChange Called");
console.log(test.value);
} // Called when the input element loses focus and its value changed
test.oninput = () => {
console.log("OnInput Called");
console.log(test.value);
} // Called whenever the input value changes
test.onkeyup = () => {
console.log("OnKeyUp Called");
console.log(test.value);
} // some pre-HTML5 way of getting real-time input value changes
}
</script>
</head>
<body>
<input type="text" name="test" id="test">
</body>
</html>
但是,当以编程方式更改输入元素的值时,这些事件都不会触发,就像有人执行
document.getElementById("test").value = "Hello there!!";
要捕获以编程方式更改的值,过去通常可以执行以下两种操作之一:
1) 告诉编码人员每次以编程方式更改输入值时手动触发 onchange 事件,例如
document.getElementById("test").value = "Hello there!!";
document.getElementById("test").onchange();
但是,对于手头的这个项目,客户不会接受这种解决方案,因为他们有许多来来去去的承包商/分包商,我猜他们只是不相信他们的承包商会严格遵守这种规则,更重要的是,他们从之前的契约(Contract)中得到了一个可行的解决方案,这是第二种旧的做事方式
2)设置一个计时器,定期检查输入元素值并在其更改时调用函数,如下所示
var pre_value = test.value;
setInterval(() => {
if (test.value !== pre_value) {
console.log("Value changed");
console.log(test.value);
pre_value = test.value;
}
}, 200); // checks the value every 200ms and see if it's changed
这看起来像是 jQuery v1.6 时代的恐龙,恕我直言,由于各种原因,这相当糟糕,但不知何故适合客户的要求。
现在已经是 2019 年了,我想知道是否有一些现代的方法来替换上述代码? JavaScript setter/getter 看起来很有前途,但是当我尝试以下代码时,它只是破坏了 HTML 输入元素
Object.defineProperty(test, "value", {
set: v => {
this.value = v;
console.log("Setter called");
console.log(test.value);
},
get: ()=> {
console.log("Getter called");
return this.value;
}
});
当以编程方式分配 test.value 时,将调用 setter 函数,但 HTML 页面上的输入元素会以某种方式被破坏。
那么,除了古老的“使用轮询计时器”方法之外,您是否知道如何捕获 HTML 输入元素值的所有更改并调用处理函数?
注意:请注意,这里的所有代码仅用于示例目的,不应在实际系统中使用,最好使用 addEventListener/attachEvent/dispatchEvent/fireEvent 等方法
最佳答案
要观察对元素的 .value
的赋值和检索,Object.defineProperty
是可行的方法,但您需要调用原始 自定义方法中的 setter 和 getter 函数,可在 HTMLInputElement.prototype
上找到:
const { getAttribute, setAttribute } = test;
test.setAttribute = function(...args) {
if (args[0] === 'value') {
console.log('Setting value');
}
return setAttribute.apply(this, args);
};
test.getAttribute = function(...args) {
if (args[0] === 'value') {
console.log('Getting value');
}
return getAttribute.apply(this, args);
};
test.setAttribute('value', 'foo');
console.log(test.getAttribute('value'));
<input type="text" name="test" id="test">
注意使用方法而不是箭头函数 - 这很重要,它允许保留 this
上下文。 (您也可以使用诸如 set.call(input, v)
之类的方法,但这不太灵活)
这仅适用于对 .value
的更改。如果你愿意,你可以为 setAttribute('value
) 打上类似的代码:
const { setAttribute } = test;
test.setAttribute = function(...args) {
if (args[0] === 'value') {
console.log('attribute set!');
}
return setAttribute.apply(this, args);
};
test.setAttribute('value', 'foo');
<input type="text" name="test" id="test">
关于javascript - 捕获 HTML 输入元素值的所有更改的现代方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55332114/