簡體   English   中英

觸發DOM屬性更改事件

[英]Firing event on DOM attribute change

有什么方法可以在屬性更改時觸發事件(可能是自定義的)?

比方說,當IMG src更改或DIV的innerHtml嗎?

注意:自2012年起,突變事件已從標准中刪除,現已棄用。 有關如何使用其替代品MutationObserver ,請參見其他答案或文檔。

您指的是DOM突變事件 瀏覽器對這些事件的支持較差(但正在改善)。 jQuery的Mutation Events插件可能會為您提供一些幫助。

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

希望這可以幫助。

如果只需要特定的東西,則每隔幾毫秒檢查一次目標屬性,即可使用一個簡單的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更改事件。

這里的好文章試圖以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的MutationObserver示例用法啟發的Mats回答之外:

如果您的選項包含<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元素的track屬性更改。 我使用了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> 

希望這可以幫助您跟蹤任何屬性更改,還可以插入新元素。讓我們嘗試一下,讓我知道您是否遇到任何問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM