在内容脚本加载到Chrome扩展程序之前,如何避免出现样式错误的内容?

shanzilla

我正在尝试创建我的第一个Chrome浏览器扩展程序。它应使用内容脚本在指定域的每个页面上操纵DOM。最初,我style.css仅使用要处理的页面中已经存在的选择器来创建样式规则-此方法按预期工作。

然后,我决定通过添加选项来扩展功能,允许用户从与3种不同样式规则相关的3种状态中进行选择。我添加scripts.js了一个基于所选选项设置的类,该选项将用作选择器以应用适当的样式规则。问题在于,现在我必须等待从chrome存储读取状态,然后才能应用自定义类,这意味着在我的样式生效之前,页面上会闪烁默认样式。

我应该使用什么方法来防止样式加载之前的延迟?

manifest.json(部分)

"content_scripts": [
  {
    "js": [ "scripts.js" ],
    "css": [ "style.css" ],
    "matches": [ "https://example.com/*" ]
  }
]

scripts.js

chrome.storage.sync.get("state", function (obj) {
  var elem = document.getElementById('targetId');

  if (obj.state === 'targetState') {
    elem.className += ' myClass';
  }

});

style.css

.myClass {
  /* do something */
}
wOxxOm

时尚的chrome扩展程序通过以下步骤解决了此问题:

  1. 将状态缓存在后台页面脚本变量中,然后将其发送回内容脚本,该脚本将在开始时请求数据。
  2. (可选)从chrome.webNavigation.onCommitted向内容脚本发送一条消息,该消息发生在页面开始加载之前,有时甚至在内容脚本运行之前,因此此方法只是一种附加措施。但是,可以通过在后台页面脚本中使用setInterval发送多次相同的消息来使其成为唯一的方法。
  3. 使用"persistent": true 背景页面可以说,这是在这种通信情况下可靠地避免FOUC的唯一方法,因为非持久事件页需要一些时间才能加载。
  4. 声明要在“ document_start”处注入的内容脚本
    当内容脚本执行时,文档为空,没有头,没有正文。此时,时尚扩展,其功能是样式注入,只需直接在下方添加样式元素<html>

在您的情况下,需要执行其他步骤:

  1. 使用MutationObserver在页面加载过程中对其进行处理(例如性能信息)。

manifest.json:

"background": {
    "scripts": ["background.js"]
},
"content_scripts": [
    {
        "js": ["contents.js"]
        "matches": ["<all_urls>"],
        "run_at": "document_start",
        "all_frames": true,
    }
],

内容脚本:

var gotData = false;

chrome.runtime.sendMessage({action: 'whatDo'}, doSomething);

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

function doSomething(msg) {
    if (gotData || !msg || !msg.data)
        return;

    gotData = true;

    new MutationObserver(onMutation).observe(document, {
        childList: true, // report added/removed nodes
        subtree: true,   // observe any descendant elements
    });

    function onMutation(mutations, observer) {
        // use the insanely fast getElementById instead of enumeration of all added nodes
        var elem = document.getElementById('targetId');
        if (!elem)
            return;
        // do something with elem
        .............
        // disconnect the observer if no longer needed
        observer.disconnect();
    }
}

后台页面脚本:

var state;

chrome.storage.sync.get({state: true}, function(data) {
    state = data.state;
});

chrome.storage.onChanged.addListener(function(changes, namespace) {
    if (namespace == 'sync' && 'state' in changes) {
        state = changes.state.newValue;
    }
});

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    if (msg.action == 'whatDo') {
        sendResponse({action: 'doSomething', data: state});
    }
});

chrome.webNavigation.onCommitted.addListener(function(navDetails) {
    chrome.tabs.sendMessage(
        navDetails.tabId,
        {action: 'doSomething', data: state},
        {frameId: navDetails.frameId}
    );
});

重复消息传递,一个简单的示例,它不检查消息是否已处理:

chrome.webNavigation.onCommitted.addListener(function(navDetails) {
    var repetitions = 10;
    var delayMs = 10;
    send();

    function send() {
        chrome.tabs.sendMessage(
            navDetails.tabId,
            {action: 'doSomething', data: state},
            {frameId: navDetails.frameId}
        );
        if (--repetitions)
            setTimeout(send, delayMs);
    }
});

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何包含Chrome扩展程序内容脚本的样式?

Chrome扩展程序:如何全局捕获/处理内容脚本错误?

Chrome扩展程序-在内容脚本中接收请求

Chrome扩展程序:内容脚本注入时如何解决“不允许加载本地资源”错误

Chrome扩展程序-在URL更新上加载内容脚本

如何在Chrome扩展程序内容脚本中获取错误堆栈跟踪?

InnerText在内容脚本Chrome扩展程序中返回未定义的

Chrome扩展程序:尝试在内容脚本中使用require.js

如何选择何时启动Chrome扩展程序的内容脚本?

如何取消Chrome扩展程序内容脚本中的事件绑定?

Chrome扩展程序:注入后如何删除内容脚本CSS?

内容脚本之间的通信| Chrome 扩展程序

chrome.runtime.sendMessage在重新加载Chrome扩展程序后从内容脚本抛出异常

chrome扩展程序-使用内容脚本时减少加载时间的最佳方法

使用相对路径时无法加载chrome扩展程序内容脚本

内容脚本未加载图片和FontAwesom图标-Chrome扩展程序

刷新页面后才加载Chrome扩展程序内容脚本

Firefox/Chrome Web 扩展 - 尝试通过内容脚本注入 IFrame 时出现安全错误

在内容脚本之前注入javascript变量

在Chrome扩展程序中将远程脚本作为内容脚本

动态加载内容脚本(chrome扩展名)

Web扩展程序是否需要显式加载内容脚本?

动态地注入内容脚本 - Chrome扩展程序

Chrome扩展程序内容脚本未触发代码

Chrome扩展程序:内容脚本未找到dom元素

Chrome扩展程序的内容脚本不影响特定网站

Chrome扩展程序:检查是否已插入内容脚本

使用背景页面和内容脚本的Chrome扩展程序

Chrome扩展程序后台页面和内容脚本同步