/"/>

关于ajax:如何执行动态加载的JavaScript块?

关于ajax:如何执行动态加载的JavaScript块?

How do you execute a dynamically loaded JavaScript block?

我正在一个网页上进行AJAX调用,该调用返回的HTML块如下:

1
2
3
  <!-- some html -->
  <script type="text/javascript">
    /** some javascript */

我正在将整个内容插入DOM,但是JavaScript没有运行。有办法运行吗?

一些细节:我无法控制脚本块中的内容(因此无法将其更改为可以调用的函数),我只需要执行整个块即可。我无法在响应中调用eval,因为JavaScript在HTML的较大块内。我可以做某种正则表达式来分离JavaScript,然后在其上调用eval,但这真令人讨厌。有人知道更好的方法吗?


通过设置元素的innerHTML属性添加的脚本不会执行。尝试创建一个新的div,设置其innerHTML,然后将此新的div添加到DOM中。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
<script type='text/javascript'>
function addScript()
{
    var str ="alert('i am here');<\\/script>";
    var newdiv = document.createElement('div');
    newdiv.innerHTML = str;
    document.getElementById('target').appendChild(newdiv);
}

</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
hello world

</body>
</html>

如果您使用响应来填充div或其他内容,则不必使用正则表达式。您可以使用getElementsByTagName。

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

@Ed接受的答案。不适用于当前版本的Firefox,Google Chrome或Safari浏览器。我设法采用他的示例来调用动态添加的脚本。

必要的更改仅是将脚本添加到DOM的方式。代替将其添加为innerHTML的方法是创建一个新的脚本元素,然后将实际的脚本内容作为innerHTML添加到所创建的元素中,然后将该脚本元素附加到实际目标中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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);
}

</head>
<body>
<input type="button" value="add script" onclick="addScript()"/>
hello world

</body>
</html>

这适用于Firefox 42,Google Chrome 48和Safari 9.0.3


一种替代方法是不只是使用InnerHTML将Ajax调用的返回结果转储到DOM中。

您可以动态地插入每个节点,然后脚本将运行。

否则,浏览器仅假定您正在插入文本节点,而忽略脚本。

使用Eval是相当邪恶的,因为它需要启动Javascript VM的另一个实例并通过JIT传递字符串。


最好的方法可能是直接通过DOM识别并评估脚本块的内容。

不过,我会小心..如果您实施此操作是为了克服某些异地通话的限制,则说明您正在开设安全漏洞。

无论您实施哪种实施方式,都可以将其用于XSS。


对于那些喜欢危险生活的人:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// This is the HTML with script element(s) we want to inject
var newHtml = 'After!\
\
<'
+
  'script>\
\
changeColorEverySecond();\
\
</'
+
  '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>/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('\
\
'
),
        js: inner.join('\
\
'
)
    };
}

// 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;
}
1
<p>Before</p>


您可以使用一种流行的Ajax库中的一种,它本身可以为您执行此操作。我喜欢原型。您可以只将evalScripts:true作为Ajax调用的一部分添加,它会自动发生。


推荐阅读

    linux执行两次命令?

    linux执行两次命令?,系统,信息,连续,名称,命令,初级,首页,工具,管理,终端,lin

    linux命令执行安装?

    linux命令执行安装?,软件,系统,管理,网站,官网,市场,中心,最新,灵活,工作,如

    linux执行一条新命令?

    linux执行一条新命令?,系统,工作,命令,管理,网络,服务,信息,目录,路径,脚本,L

    linux执行c程序命令?

    linux执行c程序命令?,系统,工作,工具,信息,代码,命令,文件,保险,管理,环境,li

    linux命令执行中断?

    linux命令执行中断?,设备,系统,网络,工具,工作,通用,状态,名字,流程,进程,lin

    执行linux脚本命令行?

    执行linux脚本命令行?,工具,位置,地方,环境,数据,状态,暂停,增长,系统,基础,

    linux远端执行命令?

    linux远端执行命令?,系统,状态,软件,名称,密码,暂停,网络,环境,认证,在线,如

    linux命令行执行成功?

    linux命令行执行成功?,系统,信息,状态,服务,管理,百度,设计,灵活,代码,命令,L

    安卓执行linux命令行?

    安卓执行linux命令行?,系统,设备,基础,发展,标准,情况,信息,电话,号码,工具,

    c执行在linux命令?

    c执行在linux命令?,系统,环境,保险,工具,代码,命令,程序,文件,终端,语言,如何

    linux外部命令调用?

    linux外部命令调用?,系统,软件,标准,命令,盘中,管理,外部,进程,程序,内存,lin

    linux执行中退出命令?

    linux执行中退出命令?,档案,状态,命令,分析,数据,电脑,实时,系统,工具,编辑,l

    linux授权命令执行?

    linux授权命令执行?,系统,工作,数字,权限,文件,概念,标准,命令,目录,用户,在L

    linux怎么调用命令行?

    linux怎么调用命令行?,系统,地址,工具,工作,首页,终端,命令,密码,信息,情况,l

    linux定时执行命令?

    linux定时执行命令?,时间,系统,服务,任务,工作,标准,情况,周期性,工具,命令,l

    如何在linux执行命令?

    如何在linux执行命令?,单位,电脑,命令,系统,基础,发行,工具,工作,信息,文件,m

    linux看命令执行过程?

    linux看命令执行过程?,系统,服务,状态,软件,时间,数据,地址,命令,进程,情况,l

    linux登陆执行命令?

    linux登陆执行命令?,系统,服务,工具,地址,密码,百度,管理,检测,网络,第一,怎

    linux权限命令可执行?

    linux权限命令可执行?,系统,工具,信息,权限,数字,网络,发行,底部,代码,文件,l

    linux远程执行多命令?

    linux远程执行多命令?,工具,服务,命令,状态,暂停,代码,底部,时间,地址,系统,L