Я пытался загрузить некоторые скрипты на страницу, используя innerHTML
на <div>
. Похоже, что скрипт загружается в DOM, но он никогда не выполняется (по крайней мере, в Firefox и Chrome). Есть ли способ выполнить сценарии при их вставке с помощью innerHTML
?
Образец кода:
<!DOCTYPE html>
<html>
<body onload="document.getElementById('loader').innerHTML = '<script>alert(\'hi\')<\/script>'">
Shouldn't an alert saying 'hi' appear?
<div id="loader"></div>
</body>
</html>
источник
<script>
тега сinnerHTML
может быть коротким, но это не работает. Это все просто текст, пока он не пройдётeval()
. И, к сожалению,eval()
не анализирует HTML-теги, так что вы столкнетесь с цепью проблем.Вот очень интересное решение вашей проблемы: http://24ways.org/2005/have-your-dom-and-script-it-too
Так что используйте это вместо тегов скрипта:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
источник
onload
атрибута. Также для этого требуется дополнительный файл, чтобы существовать и быть загруженным. Решение Момо меньше компромисса.<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
(это не будет выполнять сетевой запрос) На самом деле ... вам НЕ нужно изображение, ссылаться на несуществующий образ и вместоonload
использованияonerror
(но это будет делать сетевой запрос)Вот метод, который рекурсивно заменяет все скрипты исполняемыми:
Пример вызова:
источник
Вы можете создать скрипт, а затем внедрить содержимое.
Это работает во всех браузерах :)
источник
document.documentElement
вместо этого.<script>
var g = document.createElement('script');
var s = document.getElementsByTagName('script')[0]; //reference this script
g.text = "alert(\"hi\");"
s.parentNode.insertBefore(g, s);
</script>
<script>
элементов. Например<img onerror="..." src="#">
и<body onload="...">
. Если вы хотите быть техническим, это не будет работать в документах не HTML / SVG из-за неявного пространства имен.Я использовал этот код, он работает нормально
источник
У меня была эта проблема с innerHTML, мне пришлось добавить скрипт Hotjar в тег «head» моего приложения Reactjs, и он должен был выполняться сразу после добавления.
Одним из хороших решений для динамического импорта узлов в тег head является модуль React-helment .
Также есть полезное решение для предложенного вопроса:
Нет тегов сценария в innerHTML!
Оказывается, HTML5 не позволяет динамически добавлять теги сценария с помощью свойства innerHTML. Таким образом, следующее не будет выполнено, и не будет никакого предупреждения, говорящего Привет Мир!
Это задокументировано в спецификации HTML5:
Но будьте осторожны, это не означает, что innerHTML безопасен от межсайтовых скриптов. Возможно выполнение JavaScript через innerHTML без использования тегов, как показано на странице innerHTML MDN .
Решение: динамическое добавление скриптов
Чтобы динамически добавить тег сценария, вам нужно создать новый элемент сценария и добавить его к целевому элементу.
Вы можете сделать это для внешних скриптов:
И встроенные скрипты:
источник
Для тех, кто все еще пытается это сделать, нет, вы не можете внедрить скрипт, используя
innerHTML
, но есть возможность загрузить строку в тег скрипта, используяBlob
иURL.createObjectURL
.Я создал пример, который позволяет вам запускать строку в качестве сценария и получать «экспорт» сценария, возвращаемый через обещание:
Я упростил это из моей реальной реализации, так что никаких обещаний, что в нем нет ошибок. Но принцип работает.
Если вам не нужно возвращать какое-либо значение после запуска скрипта, это еще проще; просто оставь
Promise
иonload
биты. Вам даже не нужно оборачивать скрипт или создавать глобальноеwindow.__load_script_exports_
свойство.источник
Вот рекурсивная функция для установки innerHTML элемента, который я использую на нашем рекламном сервере:
Вы можете увидеть демо здесь .
источник
Вы можете сделать это так:
источник
Здесь решение, которое не использует
eval
, а работает со скриптами , связанными скриптами , а также с модулями .Функция принимает 3 параметра:
источник
eval('console.log(this)')
и вы увидите самый очевидный из нихeval('let b=100')
... и затем попытайтесь получить доступb
извне eval .... удачи с ним, он вам понадобитсяКрасимир Цонев имеет отличное решение, которое преодолевает все проблемы. Его метод не требует использования eval, поэтому проблем с производительностью и безопасностью не существует. Это позволяет вам установить строку innerHTML, содержащую html с js, и немедленно преобразовать ее в элемент DOM, а также выполнить части js, существующие в коде. Короче говоря, просто и работает именно так, как вы хотите.
Наслаждайтесь его решением:
http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element
Важные заметки:
источник
Используйте
$(parent).html(code)
вместоparent.innerHTML = code
.Следующее также исправляет сценарии, которые используют,
document.write
и сценарии, загружаемые черезsrc
атрибут. К сожалению, даже это не работает со скриптами Google AdSense.Источник
источник
Попробуйте использовать template и document.importNode. Вот пример:
источник
Вы также можете обернуть
<script>
это так, и оно будет выполнено:Обратите внимание: область видимости внутри
srcdoc
относится к iframe, поэтому вы должны использоватьtop
как в примере выше, чтобы получить доступ к родительскому документу.источник
Я делаю это каждый раз, когда хочу динамически вставить тег сценария!
ПРИМЕЧАНИЕ: ES6 используется
РЕДАКТИРОВАТЬ 1: Разъяснение для вас, ребята - я видел много ответов использовать
appendChild
и хотел, чтобы вы, ребята, знали, что это работает точно так же, какappend
источник
Да, вы можете, но вы должны сделать это вне DOM, и порядок должен быть правильным.
... предупредит 'Foo'. Это не сработает:
И даже это не сработает, потому что узел вставляется первым:
источник
Мое решение этой проблемы - установить Mutation Observer для обнаружения
<script></script>
узлов, а затем заменить его новым<script></script>
узлом с тем же src. Например:источник
Упоминание Габриэля Гарсии о MutationObservers находится на правильном пути, но у меня не получилось. Я не уверен, было ли это из-за причуды браузера или из-за ошибки на моем конце, но версия, которая в итоге работала для меня, была следующей:
Конечно, вы должны заменить
element_to_watch
имя изменяемого элемента.node.parentElement.added
используется для хранения тегов сценария, которые добавляются вdocument.head
. В функции, используемой для загрузки внешней страницы, вы можете использовать что-то вроде следующего, чтобы удалить больше не релевантные теги скрипта:И пример начала функции загрузки:
источник
MutationObserver
каждый раз, когда элемент добавляется в документ, верно? Кстати, мне интересно, почему вы говорите, мой код не работает.Для меня лучший способ - вставить новый HTML-контент через innerHtml, а затем использовать
SetTimeout не требуется, но работает лучше. Это сработало для меня.
источник
Выполнить (Java Script) тег из innerHTML
Замените ваш элемент скрипта на div с атрибутом class class = "javascript" и закройте его
</div>
Не изменяйте содержимое, которое вы хотите выполнить (раньше это было в теге script, а теперь в теге div)
Добавить стиль на своей странице ...
<style type="text/css"> .javascript { display: none; } </style>
Теперь запустите eval, используя jquery (Jquery js должен быть уже включен)
Вы можете узнать больше здесь , в моем блоге.
источник