【问题标题】:Firing event on DOM attribute changeDOM 属性更改时触发事件
【发布时间】:2011-06-01 12:03:37
【问题描述】:

有没有办法在属性更改时触发事件(可能是自定义的)?

比方说,当IMG src 或DIV 的innerHtml 发生变化时?

【问题讨论】:

标签: javascript jquery dom events dom-events


【解决方案1】:

注意:自 2012 年起,突变事件已从标准中删除,现已弃用。请参阅其他答案或文档以了解如何使用它们的替换,MutationObserver

您指的是DOM Mutation Events。浏览器对这些事件的支持很差(但正在改进)。 Mutation Events plugin for jQuery 可能会给你一些帮助。

【讨论】:

  • DOM 突变事件实际上在浏览器中得到了相当好的支持。只是 IE 根本不支持它们(虽然 IE 9 会)。
  • @TimDown 如果是 IE,这并不奇怪。
  • 现在不推荐使用这些,取而代之的是 MutationObserver, developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • 对我来说这个答案太简洁了。我不知道如何使用 jquery 插件。但是 Mats 的回答很简单,不需要额外的插件。
【解决方案2】:

如何设置 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();

希望这会有所帮助。

【讨论】:

  • 像 Chrome 中的魅力一样工作。真的很有用!
【解决方案3】:

如果您只需要特定的东西,那么简单的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 中的各种属性,而不会注意到性能下降。
  • MutationObserver 可能是一个更优雅的解决方案,但如果相关元素尚未生成怎么办?出于调试目的,我认为暂时让事情有点混乱是可以的。我目前的用例是试图找出导致错误更改旧系统中的值的原因,所以这个解决方案实际上比更干净的解决方案更适合我。
【解决方案4】:

没有可以挂钩的本地 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);
        }
    } }

【讨论】:

  • 这种方法对性能有相当大的影响。
  • “好文章”链接坏了:(
【解决方案5】:

除了受MDN's MutationObserver Example usage启发的Mats' answer

如果您的 options 包含 &lt;property&gt;: 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);
...

【讨论】:

    【解决方案6】:

    我遇到了同样的问题,我必须找到某些特定 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>

    我希望这将帮助您跟踪任何属性更改,以及新元素的插入.. 让我们试试,如果您遇到任何问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多