Почему 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 правильно.

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.
}

... ...
Другие вопросы по тегам