Javascript 什么';捕捉HTML输入元素值的所有更改的现代方法是什么?
是否有一种标准方法可以捕获对HTML输入元素值的所有更改,而不管它是由用户输入更改的还是以编程方式更改的Javascript 什么';捕捉HTML输入元素值的所有更改的现代方法是什么?,javascript,html,Javascript,Html,是否有一种标准方法可以捕获对HTML输入元素值的所有更改,而不管它是由用户输入更改的还是以编程方式更改的 考虑下面的代码(这纯粹是为了示例的目的而不是用良好的编码实践编写的),您可以认为它是一些能够在一些Web浏览器中运行的伪代码:P) 要捕获以编程方式更改的值,过去通常可以执行以下两种操作之一: 1) 告诉程序员在每次以编程方式更改输入值时手动触发onchange事件,如 document.getElementById("test").value = "Hello there!!"; docu
考虑下面的代码(这纯粹是为了示例的目的而不是用良好的编码实践编写的),您可以认为它是一些能够在一些Web浏览器中运行的伪代码:P)
要捕获以编程方式更改的值,过去通常可以执行以下两种操作之一: 1) 告诉程序员在每次以编程方式更改输入值时手动触发onchange事件,如document.getElementById("test").value = "Hello there!!";
document.getElementById("test").onchange();
然而,对于手头的这个项目,客户不会接受这种解决方案,因为他们有很多承包商/分包商来来往往,我猜他们只是不相信他们的承包商严格遵守这种规则,更重要的是,他们从以前的一份合同中找到了一个可行的解决方案,这是第二种老办法
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
这看起来像是jqueryv1.6时代的恐龙,这在IMHO中是非常糟糕的,但在某种程度上满足了客户的需求
现在我们是在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
的赋值和检索,对象。defineProperty
是一种方法,但是您需要在自定义方法中调用原始的setter和getter函数,这些函数可在HTMLInputElement.prototype
上找到:
const{getAttribute,setAttribute}=test;
test.setAttribute=函数(…参数){
if(args[0]=“value”){
console.log(“设置值”);
}
返回setAttribute.apply(此参数为args);
};
test.getAttribute=函数(…args){
if(args[0]=“value”){
log(“获取值”);
}
返回getAttribute.apply(此参数为args);
};
test.setAttribute('value','foo');
log(test.getAttribute('value'))代码>
标准方法是在以编程方式更改值时不触发更改事件。
不仅以编程方式设置输入值的方法太多,而且,这只是对无止境循环的调用
如果在任何回调中设置了输入值,则会使页面崩溃
想试试吗
let called=0;//要避免阻止此页面,请执行以下操作:
const{set,get}=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,“value”);
Object.defineProperty(inp,'值'{
集合(v){
const ret=set.call(this,v);
if(++called<20)//我将其限制为20次调用以不终止此页面
这是dispatchEvent(新事件(“所有变更”);
返回ret;
},
get(){return get.call(this);}
});
inp.addEventListener('all-changes',e=>{
inp.value=inp.value.toUpperCase();
console.log('changed');
});
btn.onclick=e=>inp.value='foo'代码>
设置值
这对您的查询是否有效?最好是调用负责更改的js应该触发的任何回调。触发事件是一种糟糕的黑客行为,系统地调用值更改回调是对无休止循环的调用。您是否只关心基于文本的输入(如问题中所述),还是希望拦截对test.setAttribute('value','foo')失败的更改对于[].files=FileList
和parent.reset()
来说,代码>也会失败,不要忘记,input.onstoopidallchange=e=>input.value=input.value.toUpperCase()代码>OnTooPidallChange有什么问题?如果在monkeypatched输入上调用这样一个函数,它看起来会按预期工作,setter和getter会被正确截获,而onstoopidallchange
对此不会更明智;-)试一试(从你不太喜欢的标签上)@hellopeach诚实地说?我想他们只是幸运地发现它没有坠毁。但与此同时,他们的代码只会因为某种抖动函数(inp.value=inp.value+Math.random()-0.5
)而失败,因为他们正在检查实际的变化。说真的,这是一个坏主意,你应该让他们知道,并试图理解这个X-Y问题的X。是的。。从回调内部触发回调也可能导致无限循环,但这将由编写/编辑回调的承包商执行。不是从一家实行全上限政策的公司。正如我所说,客户只是有这样的要求,他们宁愿使用古老的轮询计时器,也不愿告诉他们的承包商/分包商遵守规则,在以编程方式分配输入值后显式调用正确的函数。这样,你就不得不向客户解释他们的请求不是一个好主意,他们应该考虑复习。当然,作为客户,他们有最终决定权,但既然你要求的是标准方式,就在这里。
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
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;
}
});