MutationObserver和当前/计算的CSS样式 [英] MutationObserver and current/computed CSS styles

查看:537
本文介绍了MutationObserver和当前/计算的CSS样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MutationObserver查找添加的图像到网页。由于许多图像通过CSS background-image 属性显示,因此除了查找 img 标签,例如...

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

然而,似乎在触发突变事件的节点和正在应用的CSS规则之间存在延迟因此在突变事件期间似乎没有 backgroundImage ,即使稍后会有。当代码在调试期间工作时(使用断点步进),但在运行时无法工作时,我注意到了这一点。使用 setTimeout 延迟突变事件处理也是可行的,但要确保延迟需要非常大并且每页之间的变化(我不确定CSS规则是什么时候保证被应用)。一个可能的原因可能仅仅是CSS内容的延迟加载或注入。

实现此功能的最佳方式是什么?我想我是在改变风格之后,但是我怀疑这是否存在。

解决方案

这适用于我。 ..


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

      var observer = new MutationObserver(parseMutations); 
    observer.observe(document,{
    ...
    attributes:true,
    attributeFilter:[style]
    });

    ...

    if(mutation.attributeName)//我们假设它是样式
    parseNode(mutation.target); //检查style.backgroundImage并调用filterNode()

    这适用于 em> setAttribute(style,...) element.style.whatever = something


  2. 使用突变捕获新的样式链接元素观察者,添加 onload 事件并分析适用的节点...

      var stylenodes = [STYLE,LINK]; 

    ...

    (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);

    ...

    //捕获stylenodes的加载并解析所有新规则
    var currentLoadedStyles = [];
    var styleLoaded = function(){
    //检查所有样式并查找刚刚添加了一些规则的
    (var i = 0; i< document.styleSheets.length; ++(i)
    {
    if(document.styleSheets [i] .rules&&& document.styleSheets [i] .rules.length> 0&&& amp; currentLoadedStyles.indexOf(document。 styleSheets [i])== -1)
    {
    currentLoadedStyles.push(document.styleSheets [i]);
    parseNewStyle(document.styleSheets [i] .rules);
    }
    }
    };

    //寻找具有背景图像的规则并重新过滤所有适用于
    的节点var parseNewStyle = function(rules){
    for(var i = 0; i< ; rules.length; ++ i)
    {
    //如果任何规则包含背景图像(可以在此查找任何内容)
    if(rules [i] .style& & rules [i] .style.backgroundImage&&规则[i] .style.backgroundImage!=none)
    {
    //获取所有受影响的节点并重新解析它们
    var nodes = document.querySelectorAll(rules [i] .selectorText); (var j = 0; j< nodes.length; ++ j)
    filterNode(nodes [j]);
    }
    }
    };



I'm using a MutationObserver to look for added images to a web page. As many images are displayed via the CSS background-image property, I'm checking the current/computed CSS style in addition to looking for img tags, for example...

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

However, it seems there is a delay between a node triggering a mutation event and the CSS rules being applied so there appears to be no backgroundImage during the mutation event even though there will be at some point later. I noticed this when the code worked during debugging (stepping with breakpoints) but didn't work at runtime. Delaying mutation event processing with setTimeout also works but to be certain the delay needs to be quite large and changes from page to page (I'm not sure exactly when the CSS rules are guaranteed to be applied). A possible cause may simply be the delayed load or injection of CSS content.

What's the best way to achieve this functionality? I guess I'm after an on-style-change mutation, but I doubt this exists.

解决方案

This works for me...

  1. Use a mutation observer to catch changes to the style attribute...

    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()
    

    This works for both setAttribute("style", ...) and element.style.whatever = something.

  2. Catch new style and link elements with the mutation observer, add an onload event and parse applicable nodes...

    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]);
            }
        }
    };
    

这篇关于MutationObserver和当前/计算的CSS样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆