我需要利用这个DOM事件。 IE有onpropertychange,这也是我需要它做的事情。但是,Webkit似乎不支持此事件。有没有我可以使用的替代方案?
答案 0 :(得分: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
答案 1 :(得分: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);
}
答案 2 :(得分:3)
我有同样的问题并且正在考虑修改setAttribute
,所以看到what Sean did,我复制了它。工作得很好,除了它在一个属性被重复设置为相同值时触发,所以我在我的副本中添加了一个检查,以便在没有更改值时跳过触发事件。我还根据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();
答案 3 :(得分:0)
请参考代码: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified'+(IE的'propertychange')就像你的情况一样在那里使用。如果它不适合你,那么能满足这种需求的“丑陋”解决方案应该是setInterval(function(){},delay) 否则请参阅上面的Sean Hogan帖子。
答案 4 :(得分: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)中测试的。