Почему script.onload не работает в пользовательском скрипте Chrome?

Я хочу загрузить другой файл скрипта на сайт, используя пользовательский скрипт. Но событие js.onload работает неправильно.

Файл пользовательского скрипта:

// ==UserScript==
// @name           Code highlight
// @description    Test
// @include        http://localhost/*
// @version        1.0
// ==/UserScript==

var js = document.createElement('script');
    js.src = "http://localhost/test/js/load.js";
    document.getElementsByTagName("head")[0].appendChild(js);
    js.onload = function(){
        console.log(A)
    }

файл load.js:

var A = {
    name:'aa'
}


В Chrome консоль выводит "undefined", но load.js загружен полностью.

Я протестировал его в Firefox, и он правильно выводит A.


person chunterg    schedule 29.05.2013    source источник
comment
Обратите внимание, что это работало только в FF + Greasemonkey, потому что @grant по умолчанию было none. Как только вы попытаетесь использовать какие-либо функции GM_ API, скрипт также сломается на FF.   -  person Brock Adams    schedule 29.05.2013


Ответы (1)


Никогда не используйте .onload, .onclick и т. д. из пользовательского скрипта. (Это также плохая практика на обычной веб-странице).

Причина в том, что пользовательские скрипты работают в изолированной программной среде ("изолированный мир"), и вы не можете установить или использовать javascript для области страницы. объекты в пользовательском скрипте или контент-скрипте Chrome.

Всегда используйте addEventListener() (или аналогичную библиотечную функцию, например jQuery .on()). Кроме того, вы должны установить load слушателей перед добавлением <script> узлов в DOM.

Наконец, если вы хотите получить доступ к переменным в области страницы (в данном случае A), вы должны вставить код, который делает так. (Или вы можете переключиться на Tampermonkey и использовать unsafeWindow, но Chrome 27 вызывает проблемы с этим.)

Используйте что-то вроде:

addJS_Node (null, "http://localhost/test/js/load.js", null, fireAfterLoad);

function fireAfterLoad () {
    addJS_Node ("console.log (A);");
}

//-- addJS_Node is a standard(ish) 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);
}


А может быть:

addJS_Node (null, "http://localhost/test/js/load.js", null, fireAfterLoad);

function fireAfterLoad () {
    addJS_Node (null, null, myCodeThatUsesPageJS);
}

function myCodeThatUsesPageJS () {
    console.log (A);
    //--- PLUS WHATEVER, HERE.
}

... ...
person Brock Adams    schedule 29.05.2013
comment
@BrockAdams scriptNode.addEventListener ("load", runOnLoad, false); для чего здесь ложь? - person vidit jain; 17.06.2015
comment
@viditjain, см. документацию. В этом случае добавление явного , false является выбором стиля кодирования. - person Brock Adams; 17.06.2015