Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 什么';捕捉HTML输入元素值的所有更改的现代方法是什么?_Javascript_Html - Fatal编程技术网

Javascript 什么';捕捉HTML输入元素值的所有更改的现代方法是什么?

Javascript 什么';捕捉HTML输入元素值的所有更改的现代方法是什么?,javascript,html,Javascript,Html,是否有一种标准方法可以捕获对HTML输入元素值的所有更改,而不管它是由用户输入更改的还是以编程方式更改的 考虑下面的代码(这纯粹是为了示例的目的而不是用良好的编码实践编写的),您可以认为它是一些能够在一些Web浏览器中运行的伪代码:P) 要捕获以编程方式更改的值,过去通常可以执行以下两种操作之一: 1) 告诉程序员在每次以编程方式更改输入值时手动触发onchange事件,如 document.getElementById("test").value = "Hello there!!"; docu

是否有一种标准方法可以捕获对HTML输入元素值的所有更改,而不管它是由用户输入更改的还是以编程方式更改的

考虑下面的代码(这纯粹是为了示例的目的而不是用良好的编码实践编写的),您可以认为它是一些能够在一些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;
            }
        });