使用vanilla javascript和MutationObserver检测输入标记中的值更改

使用vanilla javascript和MutationObserver检测输入标记中的值更改,javascript,html,mutation-observers,Javascript,Html,Mutation Observers,我想检测输入字段中的文本/值何时更改。即使我用js更改了值,我也希望检测到这些更改 这是我到目前为止试过的 HTML: JavaScript: var observer=新的突变观察者(函数(突变){ 突变。forEach(功能(突变){ //log('突变类型:'+突变类型); if(mutation.type=='childList'){ if(突变.addedNodes.length>=1){ if(mutation.addedNodes[0].nodeName!='#text'){

我想检测输入字段中的文本/值何时更改。即使我用js更改了值,我也希望检测到这些更改

这是我到目前为止试过的

HTML


JavaScript

var observer=新的突变观察者(函数(突变){
突变。forEach(功能(突变){
//log('突变类型:'+突变类型);
if(mutation.type=='childList'){
if(突变.addedNodes.length>=1){
if(mutation.addedNodes[0].nodeName!='#text'){
//console.log('Added'+mutation.addedNodes[0]。tagName+'tag');
}
}
else if(mutation.removedNodes.length>=1){
//console.log('Removed'+mutation.removedNodes[0]。标记名+'tag'))
}
}
if(mutation.type==“attributes”){
log('Modified'+mutation.attributeName+'attribute'))
}
});   
});
var observer配置={
属性:正确,
childList:false,
characterData:false
};
//侦听对主体节点和子节点的所有更改
var targetNode=document.getElementById(“exNumber”);
observer.observe(targetNode,observer配置);

要了解发生了什么,必须弄清属性(内容属性)和属性(IDL属性)之间的区别。我不会像中那样对此进行详细阐述,因此已经有了关于该主题的优秀答案:

通过键入或通过JS更改
输入
元素的内容时:

targetNode.value="foo";
浏览器会更新
属性,但不会更新
属性(该属性会反映
默认值
属性)

然后,如果我们查看,我们将看到属性是可以使用的对象成员之一。因此,如果显式设置
属性:

targetNode.setAttribute("value", "foo");
MutationObserver将通知属性修改。但是规范列表中没有类似的属性:无法观察到
属性

如果要检测用户何时更改输入元素的内容,最简单的方法是。如果您需要捕获JS修改,请查找并比较新值和旧值

检查此项以了解不同的备选方案及其局限性

可以观察到value属性,不要浪费时间

函数更改值(事件、目标){
document.querySelector(“#”+target).value=newdate().getTime();
}
函数changeContentValue(){
document.querySelector(“#content”).value=newdate().getTime();
}
Object.defineProperty(document.querySelector(“#content”),“value”{
设置:功能(t){
警报(“#更改的内容值”);
var caller=arguments.callee
?(arguments.callee.caller?arguments.callee.caller:arguments.callee)
: ''
log('this=>',this);
console.log('event=>',event | | window.event);
log('caller=>',caller);
返回this.textContent=t;
}
});



提交(不采取行动)
更改内容
此操作有效,并保留和链接原始setter和getter,因此您所在领域的所有其他内容仍然有效

var registered = [];
var setDetectChangeHandler = function(field) {
  if (!registered.includes(field)) {
    var superProps = Object.getPrototypeOf(field);
    var superSet = Object.getOwnPropertyDescriptor(superProps, "value").set;
    var superGet = Object.getOwnPropertyDescriptor(superProps, "value").get;
    var newProps = {
      get: function() {
        return superGet.apply(this, arguments);
      },
      set: function (t) {
        var _this = this;
        setTimeout( function() { _this.dispatchEvent(new Event("change")); }, 50);
        return superSet.apply(this, arguments);
      }
    };
    Object.defineProperty(field, "value", newProps);
    registered.push(field);
  }
}
我做了一些修改,想与大家分享。真不敢相信有解决办法

在输入框中键入以查看默认行为。现在,打开DevTools并选择输入元素,然后更改其值,例如
$0.value=“hello”
。检查UI与API的区别。UI交互似乎不会直接修改
属性。如果是,它还将记录
“…通过API更改…”

let inputBox=document.querySelector(“#inputBox”);
addEventListener(“输入”,函数(){
console.log(“通过UI更改的输入值。新值:'%s',this.value”);
});
observeElement(输入框,“值”,函数(旧值,新值){
log(“通过API更改的输入值。值从'%s'更改为'%s',oldValue,newValue”);
});
函数observeElement(元素、属性、回调、延迟=0){
让elementPrototype=Object.getPrototypeOf(元素);
if(elementPrototype.hasOwnProperty(属性)){
让描述符=Object.getOwnPropertyDescriptor(elementPrototype,property);
Object.defineProperty(元素、属性、{
get:function(){
返回描述符.get.apply(这是参数);
},
集合:函数(){
设oldValue=此[属性];
descriptor.set.apply(这个,参数);
设newValue=此[属性];
if(回调类型==“函数”){
setTimeout(callback.bind(this、oldValue、newValue)、delay);
}
返回新值;
}
});
}
}

onkeyup
对我的情况没有用处。实际上,由于某种原因,我无法修改外部脚本。脚本更改输入字段的值。因此,我想检测文本何时更改。在这种情况下,请检查.tnx david。因此,唯一丑陋的解决方案是使用计时器。我不希望这就是我尝试使用observer的原因。但不幸的是,可能没有其他方法可以做到这一点。您是否有任何有关dom未更改的详细信息?毕竟我可以在浏览器窗口中看到更改。@谢谢你指出:这是错误的。我想我想说的是HTML(定义属性)而不是DOM(定义属性)。通常将属性中的更改称为HTML中的更改。无论如何,严格来说,HTML是驻留在服务器中的静态文本(它不会改变),而DOM是解析标记后产生的内存中对象(每当用户