使用用户脚本中的变量在Google Chrome的页面中注入JS?

时间:2010-09-08 21:09:41

标签: javascript variables google-chrome greasemonkey inject

我有一个在FireFox中使用unsafeWindow的脚本,因为那不起作用,我已经搜索了另一个选项,并找到了它,我只是想知道:我如何使用我的用户脚本中的变量进入unsafeWindow变通方法?

我的代码是:

// ==UserScript==
// @name   Test
// @description  Test
// @include   http://www.google*
// ==/UserScript==

var toAlert = "This is what I want to alert...";
alert("Before implementation...");
contentEval( function(){ alert(toAlert);});
alert("And after...");
function contentEval(source) {
  // Check for function input.
  if ('function' == typeof source) {
    // Execute this function with no arguments, by adding parentheses.
    // One set around the function, required for valid syntax, and a
    // second empty set calls the surrounded function.
    source = '(' + source + ')();'
  }

  // Create a script node holding this  source code.
  var script = document.createElement('script');
  script.setAttribute("type", "application/javascript");
  script.textContent = source;

  // Insert the script node into the page, so it will run, and immediately
  // remove it to clean up.
  document.body.appendChild(script);
  document.body.removeChild(script);
}

它不起作用...... 我做错了什么?

1 个答案:

答案 0 :(得分:4)

如果恰好在页面的全局范围内定义了toAlert,那么您的脚本将会起作用。

在Chrome中,扩展程序/ Greasemonkey JavaScript无法与页面JavaScript共享变量或闭包 这就是为什么你不能直接从扩展范围注入该函数到页面范围,但必须从源字符串重新创建它。

这意味着如果在页面范围中创建函数,则函数需要的任何变量或函数必须:

  1. 已在全球范围内在源页面中出现。
  2. 也可以编入源页面。
  3. 例如,像这样修改你的代码......

    //-- Must recreate the variable that the function requires.
    scriptStr  = 'var toAlert="' + toAlert +'";';
    
    //-- Now the function.
    scriptStr += '(' + source.toString() + ')();'
    
    var script = document.createElement('script');
    script.textContent = scriptStr;
    

    ......有效,但这种做法显然很混乱。

    聪明的做法是: (A)将所有JavaScript保留在扩展中;不要与页面的JavaScript交互。

    或者(B)如果你必须与页面的JS交互,或者加载像jQuery这样的库,那么将所有代码放在一个main()函数中,并将其编入源页面。< / p>

    像这样:

    function localMain ()
    {
        /*--- Put EVERYTHING inside this wrapper, functions and variables.
            Call or use nothing else that's defined in the GM script here.
            Can use objects in the source page's scope, though.
        */
    }
    
    //--- Now create the function in the page's scope and run it.
    var scriptNode          = document.createElement ("script");
    scriptNode.textContent  = localMain.toString() + "\n localMain ();";
    document.head.appendChild (scriptNode);
    

    请注意,如果您还要将库加载到页面范围内,则可能需要通过使用计时器和检查该库来延迟运行localMain()