【问题标题】:JavaScript watch event not working on DOM element objects?JavaScript 监视事件不适用于 DOM 元素对象?
【发布时间】:2011-10-20 12:12:03
【问题描述】:

我知道我可以使用watch 绑定一个回调,该回调将在对象属性更改时触发。这确实适用于通用对象,例如:

{'a':1, 'b':'7'}

所以,我认为我可以简单地这样做来绑定一个回调,该回调将在输入字段值更改时触发:

var inputDomElement = document.getElementById('someInputElement');
inputDomElement.watch('value',function (id, oldval, newval) {
    alert(oldval);
    alert(newval);
});

但这不起作用。根本不会触发。没有警报框。我已经在 Firefox 5 和 Google Chrome(最新)中尝试过。

这不是watch 的工作原理吗? watch 是否根本不适用于 DOM 元素?我认为它们只是对象 - 不是吗?

更新 1:

这里是关于 watch 是什么的 MDN 信息: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch

更新 2:

我不能使用 change 事件。因为更改仅在文本元素捕获模糊时触发。这意味着它只会在用户从该文本字段切换到另一个文本字段时触发。例如,在检查此用户名或电子邮件地址是否已被占用时,这绝不是动态的,我希望在每次不同的更改时发生这种情况。

【问题讨论】:

  • MDN 页面顶部的横幅带有黄色的“非标准”。可以解释为什么它不起作用。
  • 它适用于所有现代浏览器:Firefox 3+、Google Chrome、IE 9+、SAFARI v. 4+。另外 - 我在我的问题中确实提到我已经尝试过支持浏览器。
  • 请不要继续使用“仍在等待”更改来更新您的原始问题。没有接受的答案意味着您正在寻找正确的答案。你不需要继续“碰撞”你的问题。

标签: javascript jquery dom


【解决方案1】:

DOM 是用 C/C++ 编写的,其中获取和设置 Javascript 变量的概念并不像您或我经常想象的那样存在。您可能认为代码的实现类似于下面的代码。不幸的是,Object.watch 从未启动,因为 DOM 不会不断更新 Javascipt 值,但 Javascript 正在从 DOM 请求更新。

input.onuserchangevalue = function(){
   input.value = 'new user input'
}

想想 DOM 通常是如何工作的,每个元素都有几十个潜在的属性。

  • innerHTML,value,style.cssText,name,id,style.background,style.backgroundColor

想象一下,如果 DOM 下划线代码必须不断更新每个 DOM 元素 Javascript 属性 %) 内存和 CPU 周期将通过屋顶,必须确保属性与显示值匹配。 DOM 的内部也必须检查 Javascript 值是否可能发生了变化。

现实 - 红色药丸

基本上 DOM 不会向 javascript 提供信息,但 Javascript 会从 DOM 请求信息。这是对底层发生的事情的一个不错的 Javascript 解释。

Object.defineProperty(input, "value", {
    get : function(){ /* get C/C++ DOM value */ },
    set : function(){ /* change C/C++ DOM value */ }
   });

这解释了为什么 DOM 通常是 Javascript 的瓶颈。每次与 DOM 交互时,Javascript 都必须请求/设置内部 DOM 值。

【讨论】:

  • 您使用 .watch() 的方式以及它在 MDN 文章示例中的显示方式,他们正在观看在 javascript 中创建的 javascript 对象,而不是 DOM 对象。我确实遇到了这个问题,它可能会帮助你做你想做的事情:stackoverflow.com/questions/1269633/…
  • @Alexander 问题在于如何实现底层 DOM,而不是使用 Object.defineProperty__defineGetetr__/__defineSetter__。我在上面放了 Javascript 示例来演示它是如何有点在内部工作的。
  • 抱歉,我认为我最初的评论不清楚。我完全同意你的看法并投了赞成票。 :) 该评论旨在作为您答案的附录,并针对安德烈。很遗憾,编辑原始评论的时间已经过去了。
  • @Lime:谢谢。所以 - 故事的寓意是,DOM API 和 JS API 是不同的东西,当一个人使用 getElementById 创建 JS 对象时 - 这将简单地从 DOM 元素中获取“立即数据”,并且该对象不会与DOM 数据,所以 - 我可以将 watch 绑定到创建的 JS 对象 - 但它永远不会触发,因为它永远不会更新 - 对吧?
  • 是的。 Javascript 与 DOM 交互,DOM 与 DOM 的底层 C/C++ 代码交互。 Javascipt -> DOM -> C/C++
【解决方案2】:

您需要使用 jQuery 对象,而不是 DOM 对象。有区别。

document.getElementById("someID") //returns DOM Object

$('#someId')  //returns jQuery Object

注意:你可以做一些奇怪的事情:

$(document.getElementById("someID"))  //returns a jQuery Object

这样就可以了

$('#someInputElement').watch('value',function (id, oldval, newval) {
    alert(oldval);
    alert(newval);
});

【讨论】:

  • 嗯?我不记得“手表”在 jQuery 中。这是插件吗?
  • @Andre 是的,它是一个插件。抱歉,在我的回答中没有说明这一点,而 OP 在他的问题中没有说明。我只是假设这是他以前使用过的东西。
  • 我明白了。我知道几个插件,但我很想知道为什么默认的 javascript watch 实现不起作用:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
【解决方案3】:

如果您想跟踪文本元素的更改,为什么不直接使用 .change() 方法?

http://jsfiddle.net/rkw79/qTTsH/

$('input').change(function(e) {
    $('div').html('old value: ' + e.target.defaultValue + '<br/>'
                  + 'new value: ' + e.target.value);
})

对于即时更改,请使用 .keyup():http://jsfiddle.net/rkw79/qTTsH/1/

【讨论】:

  • 因为只有在文本元素出现模糊时才会触发更改。这意味着它只会在用户从该文本字段切换到另一个文本字段时触发。例如,当检查此用户名或电子邮件地址是否已被占用时,它在任何情况下都不是动态的,而 Id' 希望在每次更改时发生。例如 - 看看 google 或 yahoo 注册页面。
  • @Andre:那么使用 .keyup 怎么样?检查更新的帖子
  • 是的 - 我怀疑这将是你将提供的下一件事:) 问题是 - 想想有多少种方法可以更改输入字段:1)按键 2)复制/粘贴上下文菜单或通过键盘快捷键 3) 输入值已使用 JavaScript 进行了修改 4) 由浏览器或浏览器插件之一自动完成。跟踪最终结果比跟踪所有到达那里的方法更容易。
  • watch 方法确实是跟踪任何值变化的最佳方法。我要回答的唯一问题是 - 为什么原生监视方式不适用于 DOM 元素。虽然我可以轻松使用一些 pugin,例如:plugins.jquery.com/project/watch
  • DOM 元素值没有一个。相信我这个。我花了一些时间挖掘并最终编写了我自己的 jQuery 插件。如果正确实施,轮询就好了。如果您有兴趣,就在这里(很简单):github.com/nixd3v/jquery.monitor
猜你喜欢
  • 2011-11-06
  • 2015-11-26
  • 2014-05-11
  • 2017-03-23
  • 2020-06-26
  • 2014-02-18
  • 2012-04-18
  • 1970-01-01
  • 2016-03-19
相关资源
最近更新 更多