【问题标题】:Handler for dynamically created DOM nodes as they are inserted插入动态创建的 DOM 节点的处理程序
【发布时间】:2012-03-19 22:36:32
【问题描述】:

我喜欢在我不拥有或控制的页面上运行自定义脚本。很多时候,这些页面都动态创建了我想应用函数的内容。

这可能吗?如果是这样,我该怎么做?理想情况下,我正在寻找实时 jQuery 的 live 方法,除了绑定像 click 这样的事件之外,它更像是在 DOM 中加载元素时发生的事件。 load 事件适用于某些元素,但我不认为适用于所有元素......

对于这个问题,假设您无法查看或更改插入 DOM 节点的代码。我想要一种可以在用户脚本或书签中使用的技术,该技术可以在多个不相关的网站上使用。

编辑:我正在寻找可以在我的反色书签中使用的东西:JavaScript: Invert color on all elements of a page

【问题讨论】:

  • 您希望应用什么样的功能?您可以监听DOMNodeInsertedIntoDocument 事件,但这可能适用于许多您不感兴趣的插入节点。
  • 我实际上对每个节点都感兴趣。我正在更改页面上所有内容的颜色。

标签: javascript jquery dom bookmarklet userscripts


【解决方案1】:

假设您运行的是 Firefox 或 Chrome 等浏览器,您可以监听 DOMNodeInserted 事件:

$(document).on('DOMNodeInserted', function(e) {
    $(e.target).css({ color : '#c00' });
});

$('body').append('<div>test</div>');​

小提琴:http://jsfiddle.net/VeF6g/(在 IE 中可能失败)

更新: 该事件已弃用。您应该使用 MutationObserver:

var observer = new MutationObserver(function(mutationList) {
    for (var mutation of mutationList) {
        for (var child of mutation.addedNodes) {
            child.style.color = '#c00';
        }
    }
});
observer.observe(document, {childList: true, subtree: true});

// ready? Then stop listening with
observer.disconnect();

更多信息在这里:https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

【讨论】:

  • 为了随机读者,我只想注意:如果可以避免,请不要使用突变事件。详情:lists.w3.org/Archives/Public/public-webapps/2011JulSep/…
  • @Nickolay - 感谢您的参考。我知道使用这些通常是个坏主意,但对于 OP 的用例来说似乎是合理的(除其他事项外,讨论是关于用户脚本的,所以他将是唯一受缓慢或崩溃影响的人)。
【解决方案2】:

如果你无法访问像 jQuery 这样的库,这里是 only-JavaScript 中的语法:

document.addEventListener('DOMNodeInserted', nodeInsert)

function nodeInsert () {
  event.srcElement.style.color = '#ffffff'
}

我认为它应该适用于大多数浏览器。

【讨论】:

    【解决方案3】:

    这是处理节点插入事件的一种好方法。为要使用 css 添加的元素设置动画。

    <style type="text/css">
    
    /* set up the keyframes; remember to create prefixed keyframes too! */
    
    @keyframes nodeInserted {  
    from { opacity: 0.99; }
    to { opacity: 1; }  
    }
    
    #parent > button {
    animation-duration: 0.001s;
    animation-name: nodeInserted;
    }
    
    </style>
    

    #parent 是 div 的 id,我将在其中附加按钮 动态的。

    <script type="text/javascript">
    
        var insertListener = function(event){
            if (event.animationName == "nodeInserted") {
                // This is the debug for knowing our listener worked!
                // event.target is the new node!
                console.warn("Another node has been inserted! ", event, event.target);
            }
        }
    
        document.addEventListener("animationstart", insertListener, false); // standard + firefox
        document.addEventListener("MSAnimationStart", insertListener, false); // IE
        document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari
    
        setInterval(function(){
    
            var btn = document.createElement("BUTTON");
    
            var t = document.createTextNode("CLICK ME");       // Create a text node
    
            btn.appendChild(t);         
    
            document.getElementById("parent").appendChild(btn);
    
        }, 2000);
    
    </script>
    

    【讨论】:

    • 我已经实现了这个方法,并在insertListener 方法中编写了一些iframe 的响应式调整大小。奇怪的是,自定义大小调整行为仅在向下滚动到 iframe 之后发生,而不是之前发生。知道这里可能发生了什么吗?
    【解决方案4】:

    这很难实现,因为没有可行的事件来响应 DOM 更改。我宁愿坚持事件委托。

    但有些活动您可能会觉得有用或有趣。在Mozilla Developer Network's list of DOM events 你可以看到例如:

    • DOMNodeInserted,
    • DOMNodeInsertedIntoDocument,
    • DOMNodeRemoved,
    • DOMElementNameChanged,

    然而,它们都被标记为 W3C 草案。

    【讨论】:

    • 这些实现了哪些浏览器?理想情况下,我想要在 Chrome 中运行的东西。
    • “草稿”标记是对部分 MDC 编辑的疏忽。这些事件也在 DOML2 事件中,这是“推荐”。事实上,这些事件中的大多数都适用于除 IE 之外的所有东西。但如果可以的话,你应该避免使用它们,因为它们有很大的缺点(详情:lists.w3.org/Archives/Public/public-webapps/2011JulSep/…
    【解决方案5】:

    检测节点插入的通用方法是使用DOMNodeInserted 突变事件。

    我实际上对每个节点都感兴趣。我正在更改页面上所有内容的颜色。

    为此,更好的解决方案是注入一个动态样式表,使用!important 标志就足够了。如果您只想更改颜色,我建议您使用 Stylish 扩展名 (Stylish for Chrome) 而不是 GreaseMonkey。

    【讨论】:

    • 是的,但是!important 标志会破坏很多页面。我正在寻找一个智能脚本,它可以在许多不同的页面上运行并且看起来不错。
    • @Muhd 您可以选择智能选择器以仅选择特定元素。 Stylish 支持通过 @-moz-document regexp() 使用 RegExes 进行域选择 - 另请参阅 @document
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 2011-10-16
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多