21

我需要利用这个 DOM 事件。IE 有 onpropertychange,它也可以做我需要它做的事情。然而,Webkit 似乎不支持这个事件。有没有我可以使用的替代方案?

4

5 回答 5

24

尽管 Chrome 不分派DOMAttrModified事件,但自 2011 年起支持更轻量级的突变观察者,这些也适用于属性更改。

以下是文档正文的示例:

var element = document.body, bubbles = false;

var observer = new WebKitMutationObserver(function (mutations) {
  mutations.forEach(attrModified);
});
observer.observe(element, { attributes: true, subtree: bubbles });

function attrModified(mutation) {
  var name = mutation.attributeName,
    newValue = mutation.target.getAttribute(name),
    oldValue = mutation.oldValue;

  console.log(name, newValue, oldValue);
}

对于简单的属性更改,该console.log语句将打印:

<body color="black">
<script type="text/html">
document.body.setAttribute("color", "red");
</script>
</body>

安慰:

> color red black

于 2012-05-05T21:46:33.870 回答
13

如果您只对检测调用setAttribute()(而不是监视所有属性修改)感到满意,那么您可以在所有元素上覆盖该方法:

Element.prototype._setAttribute = Element.prototype.setAttribute
Element.prototype.setAttribute = function(name, val) { 
 var e = document.createEvent("MutationEvents"); 
 var prev = this.getAttribute(name); 
 this._setAttribute(name, val);
 e.initMutationEvent("DOMAttrModified", true, true, null, prev, val, name, 2);
 this.dispatchEvent(e);
}
于 2010-03-03T11:31:00.567 回答
3

我有同样的问题并且正在考虑修改setAttribute,所以看到肖恩做了什么,我复制了那个。工作得很好,除了当一个属性被重复设置为相同的值时它被触发,所以我在我的副本中添加了一个检查,如果值没有被更改,则跳过触发事件。我还添加了val = String(val),基于 setAttribute将数字强制转换为字符串的基本原理,因此比较应该预料到这一点。

我的修改版本是:

var emulateDOMAttrModified = {

  isSupportedNatively: function () {
    var supported = false;
    function handler() {
      supported = true;
    }
    document.addEventListener('DOMAttrModified', handler);
    var attr = 'emulateDOMAttrModifiedTEST';
    document.body.setAttribute(attr, 'foo'); // aka $('body').attr(attr, 'foo');
    document.removeEventListener('DOMAttrModified', handler);
    document.body.removeAttribute(attr);
    return supported;
  },

  install: function () {
    if (!this.isSupportedNatively() &&
      !Element.prototype._setAttribute_before_emulateDOMAttrModified) {
      Element.prototype._setAttribute_before_emulateDOMAttrModified = Element.prototype.setAttribute
      Element.prototype.setAttribute = function(name, val) {
        var prev = this.getAttribute(name);
        val = String(val); /* since attributes do type coercion to strings,
           do type coercion here too; in particular, D3 animations set x and y to a number. */
        if (prev !== val) {
          this._setAttribute_before_emulateDOMAttrModified(name, val);
          var e = document.createEvent('MutationEvents');
          e.initMutationEvent('DOMAttrModified', true, true, null, prev, val, name, 2);
          this.dispatchEvent(e);
        }
      };
    }
  }

};

// Install this when loaded.  No other file needs to reference this; it will just make Chrome and Safari
// support the standard same as Firefox does.
emulateDOMAttrModified.install();
于 2014-10-03T05:19:45.277 回答
0

请参考代码: https ://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ('propertychange' for IE) 在你的情况下使用。如果不适合你,可以满足这个需求的“丑”解决方案应该是 setInterval(function(){}, delay) 否则请看上面 Sean Hogan 的帖子。

于 2014-03-05T08:18:47.010 回答
0

@Filip 提供的解决方案很接近(并且当时可能已经奏效),但现在您需要请求交付旧属性值。

因此,您需要更改:

observer.observe(element, { attributes: true, subtree: bubbles });

对此:

observer.observe(element, { attributes: true, attributeOldvalue:true, subtree: bubbles });

否则,您将看不到 oldValues(取而代之的是 null。)这是在 Chrome 34.0.1847.131(官方版本 265687)m 中测试的。

于 2014-05-05T01:12:28.113 回答