Не могу добавить элемент <script> - PullRequest
268 голосов
/ 04 марта 2009

Есть идеи, почему фрагмент кода ниже не добавляет элемент script в DOM?

var code = "<script></script>";
$("#someElement").append(code);

Ответы [ 18 ]

347 голосов
/ 30 августа 2010

Хорошая новость:

Это на 100% работает.

Просто добавьте что-нибудь внутри тега скрипта, например alert('voila!');. Правильный вопрос, который вы, возможно, захотите задать, возможно, «Почему я не увидел его в DOM?» .

Карл Сведберг сделал приятное объяснение комментарию посетителя на сайте jQuery API . Я не хочу повторить все его слова, вы можете прочитать прямо там здесь (мне было трудно ориентироваться в комментариях там) .

Все методы вставки jQuery используют функция domManip внутренне для очистить / обработать элементы до и после того, как они вставлены в DOM. Одна из вещей, которые domManip Функция вытащить любой скрипт элементы, которые собираются вставить и запустить их через "рутину evalScript" а не вводить их с остальными фрагмента DOM. Вставляет скрипты отдельно, оценивает их, а затем удаляет их из DOM.

Я считаю, что одна из причин jQuery делает это, чтобы избежать "Разрешения Отказано в "ошибках, которые могут возникнуть в Internet Explorer при вставке сценарии при определенных обстоятельствах. Это также избегает неоднократно вставка / оценка того же скрипта (что может привести к проблемы), если он находится в пределах элемент, который вы вставляете и затем двигаясь вокруг DOM.

Следующим шагом я подведу итог плохих новостей, используя функцию .append() для добавления сценария.


И Плохие новости это ..

Вы не можете отладить свой код.

Я не шучу, даже если вы добавите ключевое слово debugger; между строкой, которую вы хотите установить в качестве точки останова, в итоге вы получите только стек вызовов объекта, не увидев точку останова в исходном коде, (не говоря уже о том, что это ключевое слово работает только в браузере webkit, во всех других основных браузерах это ключевое слово пропускается) .

Если вы полностью понимаете, что делает ваш код, это будет незначительным недостатком. Но если вы этого не сделаете, вы в конечном итоге добавите ключевое слово debugger; повсюду, чтобы узнать, что не так с вашим (или моим) кодом. В любом случае, есть альтернатива, не забывайте, что javascript может манипулировать HTML DOM.


Обход.

Использование JavaScript (не jQuery) для управления HTML DOM

Если вы не хотите терять возможность отладки, тогда вы можете использовать нативную манипуляцию HTML DOM на JavaScript. Рассмотрим этот пример:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

Вот оно, как в старые добрые времена, не так ли? И не забывайте очищать вещи, будь то в DOM или в памяти, для всех объектов, на которые ссылаются и которые больше не нужны, чтобы предотвратить утечки памяти. Вы можете рассмотреть этот код, чтобы очистить вещи:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

Недостаток этого обходного пути заключается в том, что вы можете случайно добавить дубликат сценария, и это плохо. Отсюда вы можете немного имитировать функцию .append(), добавив проверку объекта перед добавлением и удалив сценарий из DOM сразу после его добавления. Рассмотрим этот пример:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

Таким образом, вы можете добавить скрипт с возможностью отладки, в то же время не подвергаясь дублированию скриптов. Это всего лишь прототип, вы можете расширить его так, как хотите. Я использовал этот подход и вполне доволен этим. Конечно же, я никогда не буду использовать jQuery .append() для добавления скрипта.

253 голосов
/ 04 марта 2009

Я видел проблемы, когда некоторые браузеры не учитывают некоторые изменения, когда вы делаете их напрямую (я имею в виду создание HTML из текста, как вы пытаетесь с помощью тега script), но когда вы делаете их с помощью встроенного -В командах дела идут лучше. Попробуйте это:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

От: JSON для jQuery

23 голосов
/ 09 февраля 2010

Возможно динамически загрузить файл JavaScript с помощью функции jQuery getScript

$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
  Display.sharePrice();
});

Теперь будет вызываться внешний скрипт, и если он не может быть загружен, он будет постепенно ухудшаться.

20 голосов
/ 04 марта 2009

Что значит "не работает"?

jQuery обнаруживает, что вы пытаетесь создать элемент SCRIPT, и автоматически запускает содержимое элемента в глобальном контексте. Вы говорите мне, что это не работает для вас? -

$('#someElement').append('<script>alert("WORKING");</script>');

Edit: Если вы не видите элемент SCRIPT в DOM (например, в Firebug) после запуска команды, это потому, что jQuery, как я уже сказал, запустит код и затем удалит элемент SCRIPT - я считаю, что элементы SCRIPT всегда добавляются к телу ... но в любом случае - размещение не имеет абсолютно никакого отношения к выполнению кода в этой ситуации.

17 голосов
/ 27 августа 2010

Это работает:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

Кажется, что jQuery делает что-то умное со скриптами, поэтому вам нужно добавить элемент html, а не объект jQuery.

14 голосов
/ 17 сентября 2013

Попробуйте это может быть полезно:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
3 голосов
/ 05 декабря 2009

Я хочу сделать то же самое, но добавить тег сценария в другой кадр!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);
3 голосов
/ 26 января 2010
<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

</script> в строковом литерале завершает весь сценарий, чтобы избежать использования "</scr" + "ipt>".

2 голосов
/ 31 января 2013

Добавление sourceURL в файл скрипта помогло, как упоминалось на этой странице: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

  1. В файле сценария добавьте оператор с sourceURL, например "// @ sourceURL = foo.js"
  2. Загрузите скрипт с помощью jQuery $ .getScript (), и скрипт будет доступен на вкладке «sources» в инструментах Chrome Dev
1 голос
/ 04 марта 2017

Вам не нужен jQuery для создания Script DOM-элемента . Это может быть сделано с ванильным ES6 так:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

Его не нужно заключать в Promise, но это позволяет разрешить обещание при загрузке сценария, помогая предотвратить условия гонки для долго выполняющихся сценариев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...