2008-09-16 3 views
34

Я работаю на веб-странице, где я делаю вызов AJAX, который возвращает кусок HTML, как:Как выполнить динамически загруженный блок JavaScript?

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

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

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

ответ

14

Сценарий, добавленный установкой свойства 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> 
+1

Этот сценарий не работает в IE 7. У IE 7 есть ошибка с функцией appendChild. – Eddie 2008-09-26 17:13:48

14

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

div.innerHTML = response; 
var scripts = div.getElementsByTagName('script'); 
for (var ix = 0; ix < scripts.length; ix++) { 
    eval(scripts[ix].text); 
} 
+7

это кажется весьма уязвимы для инъекций атак и других векторов ... – 2013-06-06 03:40:40

1

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

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

Вне всяких сомнений вы можете использовать XSS.

+0

Поправьте меня, если я ошибаюсь, но Я понимаю уязвимости XSS в таких ситуациях, это только проблема, если вы беспокоитесь о том, что кто-то может получить доступ к чужой онлайн-учетной записи и, таким образом, сможет украсть конфиденциальную информацию, но если это невозможно для пользователей, войдите на сайт, тогда это не беспокойство. – 2015-11-30 19:33:13

2

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

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

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

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

+12

Было бы очень приятно, если бы вы объяснили, как динамически вставлять каждый узел. – mandza 2014-06-04 10:53:42

0

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

-1

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

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

Вы можете прочитать здесь - JavaScript: How to prevent execution of JavaScript within a html being added to the DOM. Если это сработает для вас, пожалуйста, оставьте здесь комментарий с информацией о том, какой браузер и версия вы использовали.

5

Хотя принятый ответ от @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

Смежные вопросы