【问题标题】:window.onload works in Firefox+Greasemonkey script but not in a Chrome userscript?window.onload 适用于 Firefox+Greasemonkey 脚本但不适用于 Chrome 用户脚本?
【发布时间】:2012-12-05 19:49:00
【问题描述】:

有一个页面http://example.com/1.php照常包含javascript文件:

<script type="text/javascript" src="/util.js?1354729400"></script>

此文件包含我需要在我的用户脚本中使用的名为 exampleFunction 的函数。 我还有一个用户脚本:

// ==UserScript==
// @name          SomeName
// @namespace     http://example.com/userscripts
// @description   Greets the world
// @include       http://example.com/*
// ==/UserScript==
window.onload = function () {
        console.log(exampleFunction);
      alert("LOADED!");
}

在 Firefox 中完美运行并在 Chrome 中返回错误:

Uncaught ReferenceError: exampleFunction is not defined 

如何让它发挥作用?

【问题讨论】:

  • 尝试禁用 chrome 上的缓存或按 CTRL+F5

标签: javascript google-chrome cross-browser greasemonkey userscripts


【解决方案1】:

exampleFunction 未定义的原因是 Chrome 用户脚本在沙盒 ("isolated world") 中运行。请注意,Greasemonkey 脚本也经常在沙箱中运行,但您的当前运行在 an implicit @grant none
如果您的脚本使用GM_ 函数,它也会在Firefox 中停止工作。

要使此脚本在两种浏览器(以及其他一些浏览器)上都能运行,请使用 Script Injection similar to this answer

然而,还有另一个问题,因为该脚本使用的是window.onloadChrome userscripts, with the default execution start-mode, will often never see the onload event.

要解决这个问题,请将// @run-at document-end 添加到元数据块中。

所以脚本变成了:

// ==UserScript==
// @name            SomeName
// @namespace       http://example.com/userscripts
// @description     Greets the world
// @include         http://example.com/*
// @run-at          document-end
// @grant           none
// ==/UserScript==

function GM_main () {
    window.onload = function () {
        console.log(exampleFunction);
        alert("LOADED!");
    }
}

addJS_Node (null, null, GM_main);

//-- This is a standard-ish utility function:
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    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);
}

【讨论】:

  • 它并不总是有效...而且我无法确定原因
  • 如何“不工作”? 究竟有什么症状?使用答案中的脚本,除了@include 行之外没有任何变化。 页面的 URL 是什么 脚本似乎无法正常工作?该页面是否需要很长时间才能完全加载? onload 在最后一张大图等下载完成之前不会触发。
  • 自己试一试:删除“console.log(exampleFunction);”并从脚本中留下“警报”。留在此页面上,单击您的个人资料链接并刷新该页面几次。它如何为您工作?在一半的情况下,我根本没有收到 onload 事件
  • @aljesco,我做到了,它在每一个页面加载或刷新时都有效,没有失败。您使用的是哪个版本的 Chrome?什么操作系统?您的症状和错误信息是什么?暂时禁用所有其他扩展,然后重试。
【解决方案2】:

如果您想要等价于onLoad,它在页面上的所有图像加载之前不会触发,您想在元数据块中使用// @run-at document-idle。默认值 document-end 在加载 DOM 时触发,相当于 document.ready。

【讨论】:

    【解决方案3】:

    你试过用括号调用示例函数吗? :) 像这样:

    console.log(exampleFunction());
    

    如果你在 chrome 控制台中尝试,你必须添加括号来调用函数。

    【讨论】:

    • 如果 exampleFunction 真的未定义,那将不会做任何事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多