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

发布于 2024-09-18 11:18:11 字数 1140 浏览 13 评论 0原文

我有一个在 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);
}

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

I am having a script that used unsafeWindow in FireFox, since that did not work, I have searched for another option, and found it, I am only wondering: How can I use a variable from my userscript into the unsafeWindow workaround?

My code is:

// ==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);
}

And it does not work...
What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一念一轮回 2024-09-25 11:18:11

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

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

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

  1. 已全局存在于源页面中。
    或者
  2. 也将脚本编写到源页面中。

例如,像这样修改你的代码......

//-- 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() 函数中,并将其编写到源页面中。

像这样:

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

Your script would work if toAlert happened to be defined in the page's global scope.

In Chrome, extension/Greasemonkey JavaScript cannot share variables or closures with the page JavaScript.
That's why you can't inject that function directly, from the extension scope to the page scope, but have to recreate it from a source string.

This means that if you create a function in the page scope, any variables or functions that your function requires must either:

  1. Already be present, globally, in the source page.
    Or
  2. Be scripted into the source page also.

For example, modifying your code like so...

//-- 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;

... works, but this approach obviously gets messy.

The smart thing to do is to either:
(A) keep all of your JavaScript in the extension; don't interact with the page's JavaScript.

Or (B) if you must interact with the page's JS, or load libraries like jQuery, then put all of your code in one main() function and script it into the source page.

Like so:

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

Note that if you are also loading a library into the page's scope, then you may need to delay running localMain() by use of a timer and a check for that library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文