8

我正在使用 MutationObserver 来查找添加到网页的图像。由于许多图像是通过 CSSbackground-image属性显示的,因此除了查找img标签之外,我还在检查当前/计算的 CSS 样式,例如...

var hasBackgroundImage = function(node) {
    var nodeStyle = node.currentStyle || getComputedStyle(node, null);
    return (
        nodeStyle &&
        nodeStyle.backgroundImage &&
        nodeStyle.backgroundImage != "none"
        );
};

但是,似乎在触发突变事件的节点和正在应用的 CSS 规则之间存在延迟,因此在突变事件期间似乎没有延迟,backgroundImage即使稍后会有。当代码在调试期间工作(使用断点单步执行)但在运行时不起作用时,我注意到了这一点。延迟突变事件处理setTimeout也可以,但要确定延迟需要相当大并且从页面到页面发生变化(我不确定何时保证应用 CSS 规则)。一个可能的原因可能只是延迟加载或 CSS 内容的注入。

实现此功能的最佳方法是什么?我想我正在经历一种风格变化的突变,但我怀疑这是否存在。

4

1 回答 1

16

这对我有用...

  1. 使用突变观察者来捕捉样式属性的变化......

    var observer = new MutationObserver(parseMutations);
    observer.observe(document, {
        ...
        attributes:    true,
        attributeFilter: ["style"]
    });
    
    ...
    
        if (mutation.attributeName) //we'll assume it's "style"
            parseNode(mutation.target); //check for style.backgroundImage and call filterNode()
    

    这适用 setAttribute("style", ...)element.style.whatever = something

  2. 使用突变观察者捕捉新元素,添加事件style并解析适用的节点......linkonload

    var stylenodes = ["STYLE", "LINK"];
    
    ...
    
    for (var i = 0; i < mutation.addedNodes.length; i++)
    {
        var node = mutation.addedNodes[i];
        var nodeName = node.nodeName.toUpperCase();
        if (stylenodes.indexOf(nodeName) !== -1)
            node.addEventListener("load", styleLoaded);
    
    ...
    
    //catch loading of stylenodes and parse all new rules
    var currentLoadedStyles = [];
    var styleLoaded = function() {
        //check all styles and look for one that has just added some rules
        for (var i = 0; i < document.styleSheets.length; ++i)
        {
            if (document.styleSheets[i].rules && document.styleSheets[i].rules.length > 0 && currentLoadedStyles.indexOf(document.styleSheets[i]) == -1)
            {
                currentLoadedStyles.push(document.styleSheets[i]);
                parseNewStyle(document.styleSheets[i].rules);
            }
        }
    };
    
    //look for rules with background images and re-filter all nodes it applies to
    var parseNewStyle = function(rules) {
        for (var i = 0; i < rules.length; ++i)
        {
            //if any rule contains a background-image (could look for anything here really)
            if (rules[i].style && rules[i].style.backgroundImage && rules[i].style.backgroundImage != "none")
            {
                //get all affected nodes and re-parse them
                var nodes = document.querySelectorAll(rules[i].selectorText);
                for (var j = 0; j < nodes.length; ++j)
                    filterNode(nodes[j]);
            }
        }
    };
    
于 2013-12-13T05:34:29.473 回答