Будь-яка ідея, чому фрагмент коду нижче не додає елемент сценарію до DOM?
var code = "<script></script>";
$("#someElement").append(code);
Будь-яка ідея, чому фрагмент коду нижче не додає елемент сценарію до DOM?
var code = "<script></script>";
$("#someElement").append(code);
Відповіді:
Я бачив проблеми, коли деякі веб-переглядачі не поважають деяких змін, коли ви робите їх безпосередньо (під якими я маю на увазі створення HTML з тексту, як ви намагаєтеся з тегом сценарію), але коли ви робите їх із вбудованими командами справи йдуть краще. Спробуйте це:
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );
Від: JSON для jQuery
$("#someElement")[0].appendChild( script );
Хороша новина:
Це на 100% працює.
Просто додайте щось всередині тегу сценарію, наприклад alert('voila!');. Можливо, ви, можливо, захочете поставити правильне запитання: "Чому я цього не бачив у DOM?" .
Карл Сведберг зробив приємне пояснення до коментаря відвідувача на сайті API jQuery . Я НЕ хочу повторювати все його слова, ви можете прочитати прямо тут тут (я знайшов його важко переміщатися з коментарів там) .
Усі методи вставки jQuery використовують внутрішню функцію domManip для очищення / обробки елементів до та після того, як вони вставляються в DOM. Однією з речей, яку виконує функція domManip, є витягнути будь-які елементи скрипту, які збираються вставити, та запустити їх через "процедуру evalScript", а не вставити їх з рештою фрагмента DOM. Він вставляє сценарії окремо, оцінює їх, а потім видаляє їх з DOM.
Я вважаю, що одна з причин jQuery робить це уникнути помилок "Відмовлено у дозволі", які можуть виникнути в Internet Explorer під час вставки скриптів за певних обставин. Це також дозволяє уникнути повторного вставлення / оцінки одного і того ж сценарію (що потенційно може спричинити проблеми), якщо він знаходиться в складі елемента, який ви вставляєте, а потім пересуваєтеся по DOM.
Наступне - я підсумую погані новини, використовуючи .append()функцію для додавання сценарію.
І погані новини ...
Ви не можете налагоджувати код.
Я не жартую, навіть якщо ви додасте debugger;ключове слово між рядком, який ви хочете встановити як точку розриву, ви в кінцевому підсумку отримаєте лише стек виклику об'єкта, не побачивши точки вихідного коду у вихідному коді (не кажучи вже про це ключове слово працює тільки в браузері WebKit, всі інші основні браузери , здається, опустять це ключове слово) .
Якщо ви повністю розумієте, що робить ваш код, це буде незначним недоліком. Але якщо ви цього не зробите, ви в кінцевому підсумку додасте debugger;ключове слово, щоб дізнатись, що не так у вашому (або моєму) коді. У будь-якому випадку є альтернатива, не забувайте, що JavaScript може власним чином маніпулювати HTML DOM.
Обхід.
Використовуйте javascript (не jQuery) для маніпулювання HTML DOM
Якщо ви не хочете втрачати можливість налагодження, тоді ви можете використовувати маніпуляції з власним HTML-кодом HTML DOM. Розглянемо цей приклад:
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()для додавання сценарію.
$.getScriptвбудований у jQuery.
Можливо динамічно завантажувати файл JavaScript за допомогою функції jQuerygetScript
$ .getScript ('http://www.wwhat.com/shareprice/shareprice.js', function () {
Display.sharePrice ();
});
Тепер зовнішній скрипт буде викликаний, і якщо його не вдасться завантажити, він витончено погіршиться.
eval().
Що означає «не працює»?
jQuery виявляє, що ви намагаєтесь створити елемент SCRIPT, і автоматично запускає вміст елемента в глобальному контексті. Ти мені кажеш, що це не працює для тебе? -
$('#someElement').append('<script>alert("WORKING");</script>');
Редагувати: Якщо ви не бачите елемент SCRIPT в DOM (наприклад, у Firebug) після запуску команди, це тому, що jQuery, як я вже сказав, запустить код і потім видалить елемент SCRIPT - я вважаю, що елементи SCRIPT завжди додаються до тіла ... але все одно - розміщення абсолютно не стосується виконання коду в цій ситуації.
Це працює:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
Схоже, що jQuery робить щось розумне зі сценаріями, тому вам потрібно додати HTML-елемент, а не jQuery-об’єкт.
Спробуйте це може бути корисно:
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
<script>
...
...jQuery("<script></script>")...
...
</script>
</script>В строкових літералів Завершує весь сценарій, щоб уникнути цього , "</scr" + "ipt>"можна використовувати замість.
"\x3cscript\x3e\x3c/script\x3e". У XHTML вам потрібно лише ввести коментований блок CDATA.
</що заборонено. Дивіться stackoverflow.com/questions/236073/…
Додавання sourceURL у файл сценарію допомогло, як зазначено на цій сторінці: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
Ваш сценарій виконується, ви просто не можете використовувати document.writeйого. Використовуйте попередження, щоб протестувати його та уникати використання document.write. Виписки вашого файлу js з document.writeне виконуватимуться, а решта функції буде виконана.
Це те, що я вважаю найкращим рішенням. Google Analytics вводиться таким чином.
var (function(){
var p="https:" == document.location.protocol ? "https://" : "http://";
d=document,
g=d.createElement('script'),
s=d.getElementsByTagName('script')[0];
g.type='text/javascript';
g.src=p+'url-to-your-script.js';
s.parentNode.insertBefore(g,s); })();
Вам не потрібен jQuery для створення елемента DOM Script . Це можна зробити з ваніллю 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, але це дозволяє вам вирішити обіцянку, коли скрипт завантажується, допомагаючи запобігти умовам гонки для тривалих сценаріїв.
Додавання сценарію до тіла:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
Ще один спосіб зробити це, якщо ви хочете додати код, використовуючи document.createElementметод, але використовуючи .innerHTMLзамість цього .src.
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );
Можна спробувати так
var code = "<script></" + "script>";
$("#someElement").append(code);
Єдина причина, яку ви не можете зробити, "<script></script>"це те, що рядок не дозволений всередині javascript, оскільки шар DOM не може проаналізувати, що js та що HTML.
Я написав npmпакет, який дозволяє вам взяти рядок HTML, включаючи теги скриптів, і додати його до контейнера під час виконання скриптів
Приклад:
import appendHtml from 'appendhtml';
const html = '<p>Hello</p><script src="some_js_file.js"></script>';
const container = document.getElementById('some-div');
await appendHtml(html, container);
// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)
Знайдіть його тут: https://www.npmjs.com/package/appendhtml
Просто створіть елемент, розібравши його з jQuery.
<div id="someElement"></div>
<script>
var code = "<script>alert(123);<\/script>";
$("#someElement").append($(code));
</script>
Приклад роботи: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz