【发布时间】:2011-06-01 12:03:37
【问题描述】:
有没有办法在属性更改时触发事件(可能是自定义的)?
比方说,当IMG src 或DIV 的innerHtml 发生变化时?
【问题讨论】:
-
一个查询插件可以做到这一点。 stackoverflow.com/questions/16781778/…
标签: javascript jquery dom events dom-events
有没有办法在属性更改时触发事件(可能是自定义的)?
比方说,当IMG src 或DIV 的innerHtml 发生变化时?
【问题讨论】:
标签: javascript jquery dom events dom-events
注意:自 2012 年起,突变事件已从标准中删除,现已弃用。请参阅其他答案或文档以了解如何使用它们的替换,MutationObserver。
您指的是DOM Mutation Events。浏览器对这些事件的支持很差(但正在改进)。 Mutation Events plugin for jQuery 可能会给你一些帮助。
【讨论】:
MutationObserver, developer.mozilla.org/en-US/docs/Web/API/MutationObserver
如何设置 MutationObserver,大部分是从 MDN 复制的,但为了清楚起见,我添加了自己的 cmets。
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();
希望这会有所帮助。
【讨论】:
如果您只需要特定的东西,那么简单的setInterval() 将起作用,每隔几毫秒检查一次目标属性:
var imgSrc = null;
setInterval(function () {
var newImgSrc = $("#myImg").attr("src");
if (newImgSrc !== imgSrc) {
imgSrc = newImgSrc;
$("#myImg").trigger("srcChange");
}
}, 50);
然后绑定到自定义的“srcChange”事件:
$("#myImg").bind("srcChange", function () {....});
【讨论】:
没有可以挂钩的本地 dom 更改事件。
好文章 here 试图以 jquery 插件的形式提供解决方案。
文章代码
$.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);
}
} }
【讨论】:
除了受MDN's MutationObserver Example usage启发的Mats' answer:
如果您的 options 包含 <property>: true 并且您计划在 MutationObserver 的回调函数中更改 target 的此属性,请使用以下内容来防止递归调用 -直到脚本超时、堆栈溢出等:
...
// 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);
...
【讨论】:
我遇到了同样的问题,我必须找到某些特定 DOM 元素的跟踪属性更改。我使用了 MutationObserver。
但在使用 MutationObserver 时,我还面临一个更复杂的问题。 MutationObserver 在观察变化时需要一些目标元素。
在使用 SPA(其中使用了 AJAX、Angular、react 或任何其他 javascript 框架)时,您可能已经意识到所有元素都是动态的。 那是很难设定目标的。
这里我提出了一些解决方案,我在 DOM 上应用了 MutationObserver,然后在任何元素的某些属性发生变化时发出 customEvent。
然后在下一步根据我们的要求过滤自定义事件。
// 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>
我希望这将帮助您跟踪任何属性更改,以及新元素的插入.. 让我们试试,如果您遇到任何问题,请告诉我。
【讨论】: