提问者:小点点

是否有JavaScript/jQuery DOM更改侦听器?


本质上,我希望在div的内容改变时执行一个脚本。 由于脚本是分开的(Chrome扩展中的内容脚本和网页脚本),我需要一种简单地观察DOM状态变化的方法。 我可以设置投票,但这似乎太草率了。


共3个答案

匿名用户

很长一段时间以来,DOM3突变事件是最佳的可用解决方案,但由于性能原因,它们一直被弃用。 DOM4突变观察者是不推荐的DOM3突变事件的替代品。 它们目前在现代浏览器中被实现为MutationObserver(或者在Chrome的旧版本中被实现为带有供应商前缀的WebKitMutationObserver):

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    console.log(mutations, observer);
    // ...
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

此示例侦听document及其整个子树上的DOM更改,它将在元素属性更改和结构更改时触发。 规范草案包含有效变异侦听器属性的完整列表:

ChildList

  • 如果要观察到目标子级的突变,则设置为true

属性

  • 如果要观察目标属性的突变,则将其设置为true

特征数据

  • 如果要观察目标数据的突变,则将其设置为true

子树

  • 如果不仅要观察到target的突变,而且还要观察到target的后代的突变,则将true设置为true

AttributeOldValue

    如果attributes设置为true,则
  • 设置为true,并且需要记录变异之前目标的属性值。

CharacterDataOldValue

    如果CharacterData设置为true,则
  • 设置为true,并且需要记录发生变异之前的目标数据。

AttributeFilter

  • 如果不需要观察所有属性突变,则设置为属性本地名称列表(不带命名空间)。

(此列表是截至2014年4月的最新列表;您可以查看规范中的任何更改。)

匿名用户

编辑

这个答案现在被否决了。 请看APSillers的答案。

由于这是针对Chrome扩展的,因此您不妨使用标准DOM事件-DOMSubtreeModified。 请参阅跨浏览器对此事件的支持。 Chrome从1.0开始就支持它了。

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("tree changed");
});

请参阅此处的工作示例。

匿名用户

许多站点使用AJAX动态地添加/显示/更改内容。 有时它被用来代替站点内导航,因此当前URL被编程更改,并且内容脚本不会被浏览器自动执行,因为页面并不完全是从远程服务器获取的。

>

  • MutationObserver(docs),以实际检测DOM更改:

    • 如何在页面中加载HTML内容时更改内容
    • MutationObserver在整个DOM中检测节点的性能。

    用于通过发送DOM事件来通知内容更改的站点的事件侦听器:

    • pjax:end在许多基于pjax的站点(如GitHub)使用的文档上,
      请参阅如何在pjax加载之前和之后运行jQuery?
    • 消息窗口上使用,例如在Chrome浏览器中使用Google search,
      请参阅Chrome extension detect Google search Refresh
    • spfdone在Youtube使用的文档上,
      请参阅如何在呈现页面之前检测Youtube上的页面导航并修改HTML?

    通过setInterval定期检查DOM:
    显然,这只在等待由其ID/selector标识的特定元素出现时起作用,并且它不能让您普遍检测动态添加的新内容,除非您发明了某种类型的现有内容指纹。

    在注入的DOM脚本中隐藏历史API:

    document.head.appendChild(document.createElement('script')).text = '(' +
        function() {
            // injected DOM script is not a content script anymore, 
            // it can modify objects and functions of the page
            var _pushState = history.pushState;
            history.pushState = function(state, title, url) {
                _pushState.call(this, state, title, url);
                window.dispatchEvent(new CustomEvent('state-changed', {detail: state}));
            };
            // repeat the above for replaceState too
        } + ')(); this.remove();'; // remove the DOM script element
    
    // And here content script listens to our DOM script custom events
    window.addEventListener('state-changed', function(e) {
        console.log('History state changed', e.detail, location.hash);
        doSomething();
    });
    

    侦听hashchange,popstate事件:

    window.addEventListener('hashchange', function(e) {
        console.log('URL hash changed', e);
        doSomething();
    });
    window.addEventListener('popstate', function(e) {
        console.log('State changed', e);
        doSomething();
    });
    


    有一些高级的API用于导航:webNavigation,webRequest,但是我们将使用简单的chrome.tabs.onUpdated事件侦听器来向内容脚本发送消息:

    >

  • MANIFEST.JSON:
    声明后台/事件页
    声明内容脚本
    添加“选项卡”权限。

    background.js

    var rxLookfor = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/;
    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        if (rxLookfor.test(changeInfo.url)) {
            chrome.tabs.sendMessage(tabId, 'url-update');
        }
    });
    

    content.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg === 'url-update') {
            doSomething();
        }
    });