Как выполнить динамически загруженный блок JavaScript? - PullRequest
37 голосов
/ 16 сентября 2008

Я работаю над веб-страницей, на которой я выполняю вызов AJAX, который возвращает фрагмент HTML, например:

<div>
  <!-- some html -->
  <script type="text/javascript">
    /** some javascript */
  </script>
</div>

Я вставляю все это в DOM, но JavaScript не запускается. Есть ли способ запустить его?

Некоторые подробности: я не могу контролировать, что находится в блоке скрипта (поэтому я не могу изменить его на функцию, которая может быть вызвана), мне просто нужно выполнить весь блок. Я не могу вызвать eval для ответа, потому что JavaScript находится внутри большего блока HTML. Я мог бы сделать какое-то регулярное выражение, чтобы отделить JavaScript и затем вызвать eval, но это довольно отвратительно. Кто-нибудь знает лучший способ?

Ответы [ 7 ]

15 голосов
/ 16 сентября 2008

Сценарий, добавленный установкой свойства innerHTML элемента, не выполняется. Попробуйте создать новый div, установить его innerHTML, а затем добавить этот новый div в DOM. Например:

<html>
<head>
<script type='text/javascript'>
function addScript()
{
    var str = "<script>alert('i am here');<\/script>";
    var newdiv = document.createElement('div');
    newdiv.innerHTML = str;
    document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>
14 голосов
/ 16 сентября 2008

Вам не нужно использовать регулярное выражение, если вы используете ответ для заполнения div или чего-то еще. Вы можете использовать getElementsByTagName.

div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
    eval(scripts[ix].text);
}
8 голосов
/ 17 февраля 2016

Пока принят ответ от @Ed. не работает в текущих версиях браузеров Firefox, Google Chrome или Safari. Мне удалось применить его пример для вызова динамически добавляемых сценариев.

Необходимые изменения вносятся только в способ добавления сценариев в DOM. Вместо того, чтобы добавлять его как innerHTML, нужно было создать новый элемент сценария и добавить фактическое содержимое сценария как innerHTML к созданному элементу, а затем добавить элемент сценария к фактической цели.

<html>
<head>
<script type='text/javascript'>
function addScript()
{
    var newdiv = document.createElement('div');

    var p = document.createElement('p');
    p.innerHTML = "Dynamically added text";
    newdiv.appendChild(p);

    var script = document.createElement('script');
    script.innerHTML = "alert('i am here');";
    newdiv.appendChild(script);

    document.getElementById('target').appendChild(newdiv);
}
</script>
</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
<div>hello world</div>
<div id="target"></div>
</body>
</html>

Это работает для меня в Firefox 42, Google Chrome 48 и Safari 9.0.3

2 голосов
/ 16 сентября 2008

Альтернативой является не просто сбросить возврат от вызова Ajax в DOM с помощью InnerHTML.

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

В противном случае браузер просто предполагает, что вы вставляете текстовый узел, и игнорирует сценарии.

Использование Eval является довольно злым, поскольку требует запуска другого экземпляра виртуальной машины Javascript и JIT переданной строки.

1 голос
/ 16 сентября 2008

Лучшим методом, вероятно, будет идентификация и оценка содержимого блока скрипта напрямую через DOM.

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

Все, что вы реализуете, может быть использовано для XSS.

0 голосов
/ 06 февраля 2013

Ниже немного другой подход, который использует тот факт, что если тег содержит type = "text / xml", JavaScript внутри не будет выполняться:

function preventJS(html) {
    return html.replace(/<script(?=(\s|>))/i, '<script type="text/xml" ');
}

Вы можете прочитать больше здесь - JavaScript: Как предотвратить выполнение JavaScript внутри HTML, добавляемого в DOM . Если это работает для вас, пожалуйста, оставьте здесь комментарий с информацией, какой браузер и версию вы использовали.

0 голосов
/ 17 сентября 2008

Вы можете использовать одну из популярных библиотек Ajax, которая сделает это за вас. Мне нравится Прототип . Вы можете просто добавить evalScripts: true как часть вашего вызова Ajax, и это происходит автоматически.

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