Javascript并不总是在Chrome扩展程序中运行,我应该何时运行它?

时间:2013-01-01 17:48:26

标签: javascript google-chrome google-chrome-extension content-script

我有一个Chrome扩展程序,它将CSS和Javascript注入到页面中,虽然CSS总是被注入,但Javascript只是有时工作而不是其他工作。通过不工作,我认为它已经存在,它必须处理的东西存在。

Javascript只是使用divinsertBefore移到另一个之上,但这并不总是发生,我认为这是因为它正在加载。

我的清单目前是:

{
  ...
  "content_scripts": [{
    "matches": [ "*://example.com/*" ],
     "js": [
        "js/jquery-1.8.3.min.js", "js/myjavascript.js"
      ],
      "run_at": "document_end",
      "css": [
        "css/mycss.css"
      ]
  }]
} 

我当前run_at设置为document_end因为它似乎运行得更顺畅(当它工作时),所以我认为这是需要更改的内容。

如果有人有任何建议,我们非常感谢。

编辑:有关此问题答案的后续问题已添加here,我觉得如果我将其添加到此问题中,对其他人可能会有用。

1 个答案:

答案 0 :(得分:4)

如果代码并不总是有效,则表明该元素是由页面的javascript创建/加载的。因此,您需要使用标准的AJAX感知技术来移动该div。

技术包括:定时器,变异观察器,突变事件和拦截AJAX XHR(如果适用)。这些都在其他Stack Overflow问题中讨论过,但是:变异事件被弃用/错误;拦截XHR变得混乱,可能不适用于此;和变异观察者会变得复杂。

我建议您下载并添加the waitForKeyElements() utility到您的清单。

然后移动<div>的代码变成了:

waitForKeyElements (
    "jQuery selector for div(s) you want to move",
    moveSelectDivs
);
function moveSelectDivs (jNode) {
    jNode.insertBefore ("APPROPRIATE JQUERY SELECTOR");
}


将您的清单设置为run at document_end。这相当于DOMContentLoaded - 这是$(document).ready()触发的时间。默认run_at触发太晚且无法预测。 run_at document_start不会有任何好处,因为:定时器,变异观察者等等都不会在DOMContentLoaded事件发生后才会触发 - 对于当前版本的Chrome无论如何(其他浏览器)没有相同的限制。)



替代方法,用于最快的操作但网页较慢:

关于:

  

(页面正在加载,然后你可以看到div移动),这是我希望避免的。

在使用Chrome的DOMContentLoaded之前,只有两种方法可以做任何事情:

  1. 您可以设置mycss.css隐藏div,直到您移动它为止。这可能是最具成本效益的方法,性能明智。
  2. 或者,您可以覆盖document.createElement()。这将尽可能快地响应新元素(假设它是在DOMContentLoaded之前创建的),但它可能会使整个页面的速度显着减慢。
  3. 将内容脚本设置为在document_start运行,并且必须注入覆盖代码。所以,脚本看起来像:

    addJS_Node (null, null, scriptMain);
    
    function scriptMain () {
        var _orig_createElement = document.createElement;
    
        document.createElement  = function (tag) {
            var element = _orig_createElement.call (document, tag);
    
            var movingNode      = document.querySelector ("MOVING DIV SELECTOR");
            if (movingNode) {
                var target      = document.querySelector ("TARGET DIV SELECTOR");
                if (target) {
                    target.parentNode.insertBefore (movingNode, target);
    
                    document.createElement = _orig_createElement;
                }
            }
    
            return element;
        };
    }
    
    function addJS_Node (text, s_URL, funcToRun) {
        var D                                   = document;
        var scriptNode                          = D.createElement ('script');
        scriptNode.type                         = "text/javascript";
        if (text)       scriptNode.textContent  = text;
        if (s_URL)      scriptNode.src          = s_URL;
        if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';
    
        var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
        targ.appendChild (scriptNode);
    }
    


    不要试图使用jQuery。