Javascript DOM 属性更改时触发事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4561845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Firing event on DOM attribute change
提问by ts.
Is there any way to trigger event (may be custom) on attribute change?
有没有办法在属性更改时触发事件(可能是自定义的)?
Let's say, when IMG src is changed or DIV's innerHtml?
假设,当 IMG src 或 DIV 的 innerHtml 更改时?
采纳答案by Dean Burge
Note: As of 2012, Mutation Events have been removed from the standard and are now deprecated. See other answers or documentation for how to use their replacement, MutationObserver
.
注意:截至 2012 年,Mutation Events 已从标准中删除,现已弃用。请参阅其他答案或文档以了解如何使用它们的替代品MutationObserver
。
You are referring to DOM Mutation Events. There is poor (but improving) browser support for these events. Mutation Events plugin for jQuerymight get you some of the way.
您指的是DOM Mutation Events。浏览器对这些事件的支持很差(但正在改进)。jQuery 的 Mutation Events 插件可能会给你一些帮助。
回答by Mats
How to setup a MutationObserver, mostly copied from MDNbut I've added my own comments for clarity.
如何设置 MutationObserver,主要是从MDN复制的,但为了清楚起见,我添加了自己的评论。
window.MutationObserver = window.MutationObserver
|| window.WebKitMutationObserver
|| window.MozMutationObserver;
// Find the element that you want to "watch"
var target = document.querySelector('img'),
// create an observer instance
observer = new MutationObserver(function(mutation) {
/** this is the callback where you
do what you need to do.
The argument is an array of MutationRecords where the affected attribute is
named "attributeName". There is a few other properties in a record
but I'll let you work it out yourself.
**/
}),
// configuration of the observer:
config = {
attributes: true // this is to watch for attribute changes.
};
// pass in the element you wanna watch as well as the options
observer.observe(target, config);
// later, you can stop observing
// observer.disconnect();
Hope this helps.
希望这可以帮助。
回答by David Tang
If you only need something specific then a simple setInterval()
will work, by checking the target attribute(s) every few milliseconds:
如果你只需要一些特定的东西,那么一个简单的方法setInterval()
就可以工作,通过每隔几毫秒检查一次目标属性:
var imgSrc = null;
setInterval(function () {
var newImgSrc = $("#myImg").attr("src");
if (newImgSrc !== imgSrc) {
imgSrc = newImgSrc;
$("#myImg").trigger("srcChange");
}
}, 50);
Then bind to the custom "srcChange" event:
然后绑定到自定义的“srcChange”事件:
$("#myImg").bind("srcChange", function () {....});
回答by redsquare
There is no native dom changed event you can hook into.
没有您可以挂钩的本地 dom 更改事件。
Good article herewhich tries to provide a solution in the form of a jquery plugin.
这里的好文章试图以 jquery 插件的形式提供解决方案。
Code from article
文章中的代码
$.fn.watch = function(props, callback, timeout){
if(!timeout)
timeout = 10;
return this.each(function(){
var el = $(this),
func = function(){ __check.call(this, el) },
data = { props: props.split(","),
func: callback,
vals: [] };
$.each(data.props, function(i) {
data.vals[i] = el.css(data.props[i]);
});
el.data(data);
if (typeof (this.onpropertychange) == "object"){
el.bind("propertychange", callback);
} else if ($.browser.mozilla){
el.bind("DOMAttrModified", callback);
} else {
setInterval(func, timeout);
}
});
function __check(el) {
var data = el.data(),
changed = false,
temp = "";
for(var i=0;i < data.props.length; i++) {
temp = el.css(data.props[i]);
if(data.vals[i] != temp){
data.vals[i] = temp;
changed = true;
break;
}
}
if(changed && data.func) {
data.func.call(el, data);
}
} }
回答by GeroldBroser reinstates Monica
In addition to Mats' answerinspired by MDN's MutationObserver Example usage:
除了受MDN 的 MutationObserver 示例用法启发的Mats 回答:
If your optionscontain <property>: true
and you plan to change this property of targetinside MutationObserver
's callback function, use the following to prevent recursive calls – until script timeout, stack overflow or the like:
如果您的选项包含<property>: true
并且您计划在回调函数中更改target 的此属性MutationObserver
,请使用以下内容来防止递归调用 - 直到脚本超时、堆栈溢出等:
...
// Used to prevent recursive calls of observer's callback function
// From https://stackoverflow.com/questions/4561845/firing-event-on-dom-attribute-change
let insideInitialObserverCallback = false
let callback = function(mutationsList) {
insideInitialObserverCallback = ! insideInitialObserverCallback
if ( insideInitialObserverCallback ) {
// ... change target's given property ...
}
})
let observer = new MutationObserver(callback);
...
回答by Dinesh Gopal Chand
I had same issue, where I had to find track attribute change of some particular DOM element. and I used MutationObserver.
我有同样的问题,我必须找到某些特定 DOM 元素的跟踪属性更改。我使用了 MutationObserver。
But there was one more complication what I was facing while using MutationObserver. MutationObserver is need some target element while observing change.
但是在使用 MutationObserver 时,我还面临着另一个复杂问题。MutationObserver 在观察变化时需要一些目标元素。
while working with SPA (where AJAX, Angular , react or any other javascript framework have been used), you might have realized all the elements are dynamic. that's it would be difficult to set target.
在使用 SPA(其中使用了 AJAX、Angular、react 或任何其他 javascript 框架)时,您可能已经意识到所有元素都是动态的。那很难设定目标。
Here I came with some solution where I have applied MutationObserver on DOM and then emitted customEvent when some attribute of any element gets change.
在这里,我提出了一些解决方案,我在 DOM 上应用了 MutationObserver,然后在任何元素的某些属性发生更改时发出 customEvent。
then in next step filter custom event as per our requirement.
然后在下一步中根据我们的要求过滤自定义事件。
// code to change image src in each 1000ms.
count = 0;
setInterval(function() {
dimension = `${600+count}x${400+count}`;
document.querySelector('div.image-box img').src = `https://dummyimage.com/${dimension}/000/fff`;
document.querySelector('div.image-box img').alt = dimension;
count++;
}, 1000);
function startMutationObserver(tNode, c) {
// Select the node that will be observed for mutations
const targetNode = tNode ? tNode : document;
// Options for the observer (which mutations to observe)
const config = c ? c : {
attributes: true,
childList: true,
subtree: true
};
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
targetNode.dispatchEvent(new CustomEvent('newChild', {
detail: mutation
}));
} else if (mutation.type === 'attributes') {
targetNode.dispatchEvent(new CustomEvent('attributeChange', {
detail: mutation
}));
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
// observer.disconnect();
}
// call this function to start observing DOM element change
startMutationObserver(document);
// code to listen custom event and filter custom event as per requirement
document.addEventListener('attributeChange', function(e) {
// console.log(e);
const ele = e.detail;
if (ele.target.matches('div.image-box img') && ele.attributeName == 'src') {
var src = e.detail.target.getAttribute('src');
var alt = e.detail.target.getAttribute('alt');
console.log(src, alt);
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="image-box">
<img src="https://dummyimage.com/600x400/000/fff" alt="600x400">
</div>
</body>
</html>
I hope this will help you to tracking any attribute change, insertion of new element also.. Lets try, and let me know if you are facing any issues.
我希望这能帮助您跟踪任何属性更改、新元素的插入。让我们尝试一下,如果您遇到任何问题,请告诉我。