我正在开发一个网页,我正在进行AJAX调用,返回一大堆HTML,如:
<div>
<!-- some html -->
<script type="text/javascript">
/** some javascript */
</script>
</div>
我将整个内容插入到DOM中,但JavaScript没有运行。有没有办法运行它?
一些细节:我无法控制脚本块中的内容(因此我无法将其更改为可以调用的函数),我只需要执行整个块。我无法在响应上调用eval,因为JavaScript位于更大的HTML块中。我可以做某种正则表达式来分离出JavaScript,然后在它上面调用eval,但这很令人讨厌。有人知道更好的方法吗?
答案 0 :(得分:15)
通过设置元素的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 :(得分:14)
如果您使用响应来填充div或其他内容,则不必使用正则表达式。您可以使用getElementsByTagName。
div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
eval(scripts[ix].text);
}
答案 2 :(得分:8)
虽然@Ed接受了答案。不适用于当前版本的Firefox,谷歌浏览器或Safari浏览器我设法擅长他的例子,以调用动态添加的脚本。
必要的更改仅限于脚本添加到DOM的方式。不是将其添加为innerHTML
,而是创建一个新的脚本元素并将实际脚本内容添加到创建的元素中,然后将脚本元素附加到实际目标。
innerHTML
这适用于Firefox 42,Google Chrome 48和Safari 9.0.3
答案 3 :(得分:2)
另一种方法是不仅使用InnerHTML将Ajax调用的返回转储到DOM中。
您可以动态插入每个节点,然后脚本将运行。
否则,浏览器只假设您正在插入文本节点,并忽略脚本。
使用Eval是相当邪恶的,因为它需要启动另一个Javascript VM实例并JIT传递的字符串。
答案 4 :(得分:1)
最好的方法可能是直接通过DOM识别和评估脚本块的内容。
虽然我会小心..如果你实施这个以克服一些非现场电话的限制,你就会打开一个安全漏洞。
无论你实施什么都可以用于XSS。
答案 5 :(得分:0)
您可以使用其中一个流行的Ajax库本地为您执行此操作。我喜欢Prototype。您可以添加evalScripts:true作为Ajax调用的一部分,它会自动发生。
答案 6 :(得分:0)
对于那些喜欢危险生活的人:
// This is the HTML with script element(s) we want to inject
var newHtml = '<b>After!</b>\r\n<' +
'script>\r\nchangeColorEverySecond();\r\n</' +
'script>';
// Here, we separate the script tags from the non-script HTML
var parts = separateScriptElementsFromHtml(newHtml);
function separateScriptElementsFromHtml(fullHtmlString) {
var inner = [], outer = [], m;
while (m = /<script>([^<]*)<\/script>/gi.exec(fullHtmlString)) {
outer.push(fullHtmlString.substr(0, m.index));
inner.push(m[1]);
fullHtmlString = fullHtmlString.substr(m.index + m[0].length);
}
outer.push(fullHtmlString);
return {
html: outer.join('\r\n'),
js: inner.join('\r\n')
};
}
// In 2 seconds, inject the new HTML, and run the JS
setTimeout(function(){
document.getElementsByTagName('P')[0].innerHTML = parts.html;
eval(parts.js);
}, 2000);
// This is the function inside the script tag
function changeColorEverySecond() {
document.getElementsByTagName('p')[0].style.color = getRandomColor();
setTimeout(changeColorEverySecond, 1000);
}
// Here is a fun fun function copied from:
// https://stackoverflow.com/a/1484514/2413712
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
<p>Before</p>
答案 7 :(得分:-2)
下面是一个有点不同的方法,它使用if tag包含type =“text / 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。 如果它适合您,请在这里留下评论,其中包含您使用过的浏览器和版本的信息。