Javascript 执行<;脚本>;AJAX调用后由innerHTML注入

Javascript 执行<;脚本>;AJAX调用后由innerHTML注入,javascript,html,ajax,Javascript,Html,Ajax,有一个div叫做“Content”: 它应该由AJAX从PHP文件中填充数据,包括一个标记。但是,未执行此标记内的脚本 <div id="content"><!-- After AJAX loads the stuff that goes here --> <script type="text/javascript"> //code </script> <!-- More stuff that DOES wor

有一个div叫做“Content”:


它应该由AJAX从PHP文件中填充数据,包括一个
标记。但是,未执行此标记内的脚本

<div id="content"><!-- After AJAX loads the stuff that goes here -->
   <script type="text/javascript">
     //code
   </script>
   <!-- More stuff that DOES work here -->
</div>

//代码

如果通过Ajax在div中加载脚本块,如下所示:

<div id="content">
    <script type="text/javascript">
    function myFunction() {
      //do something
    }
    myFunction();
    </script>
</div>

另一种快速而肮脏的方法是,如果您不想使用jQuery或其他库,可以使用它来执行作为DOM文本插入的任何脚本代码。

作为DOM文本插入的JavaScript将不会执行。但是,您可以使用来实现您的目标。基本思想是将要执行的脚本移动到外部文件中,并在获得Ajax响应时创建脚本标记。然后设置脚本标记的
src
属性,瞧,它加载并执行外部脚本


另一篇StackOverflow文章也可能对您有所帮助:。

如果您不尝试将XHR返回的HTML的子集附加到文档中,那么使用jQuery对我来说“很有效”。(请参见显示jQuery的问题。)

下面是一个示例,显示了它的工作原理:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html lang="en"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>test_1.4</title> 
    <script type="text/javascript" charset="utf-8" src="jquery.1.4.2.js"></script> 
    <script type="text/javascript" charset="utf-8"> 
        var snippet = "<div><span id='a'>JS did not run<\/span><script type='text/javascript'>" +
        "$('#a').html('Hooray! JS ran!');" +
        "<\/script><\/div>";
        $(function(){
            $('#replaceable').replaceWith($(snippet));
        });
    </script> 
</head> 
<body> 
    <div id="replaceable">I'm going away.</div> 
</body> 
</html>

测试1.4
var snippet=“JS未运行”+
“$('a').html('Hooray!JS ran!');”+
"";
$(函数(){
$('#可替换')。替换为($(代码段));
});
我要走了。

下面是上面的等效代码:

我使用了这段代码,它工作正常

var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
    eval(arr[n].innerHTML)//run script inside div
var arr=MyDiv.getElementsByTagName('script'))
对于(变量n=0;n
我在这里有一篇类似的帖子

我的解决方法是在stateChange函数中插入对函数的调用。我设置的页面有3个按钮,可以将3个不同的页面加载到contentArea。因为我必须知道按下哪个按钮来加载第1、2或3页,所以我可以很容易地使用if/else语句来确定加载哪个页面,然后运行哪个函数。我试图做的是注册不同的按钮监听器,这些监听器只有在由于元素ID而加载特定页面时才能工作

所以

如果(正在加载page1,pageload=1) 运行函数寄存器Listeners1


第2页或第3页也是如此。

下面是脚本,它将计算文本中的所有脚本标记

function evalJSFromHtml(html) {
  var newElement = document.createElement('div');
  newElement.innerHTML = html;

  var scripts = newElement.getElementsByTagName("script");
  for (var i = 0; i < scripts.length; ++i) {
    var script = scripts[i];
    eval(script.innerHTML);
  }
}
函数evalJSFromHtml(html){
var newElement=document.createElement('div');
newElement.innerHTML=html;
var scripts=newElement.getElementsByTagName(“脚本”);
对于(变量i=0;i
从服务器接收HTML后,只需调用此函数。警告:使用
eval
可能有危险

演示:

如果您正在注入需要脚本标记的内容,则可能会出现未捕获的语法错误,并说非法令牌。要避免这种情况,请确保在结束脚本标记中转义正斜杠。ie

var输出+='';

任何结束标记(如表单标记)也是如此。

这里有一个函数可以用来解析AJAX响应,特别是如果您使用MiniFiedJ并希望它执行返回的Javascript,或者只想解析脚本而不将它们添加到DOM中,它还可以处理异常错误。我在php4sack库中使用了这段代码,它在库之外很有用

function parseScript(_source) {
    var source = _source;
    var scripts = new Array();

    // Strip out tags
    while(source.toLowerCase().indexOf("<script") > -1 || source.toLowerCase().indexOf("</script") > -1) {
        var s = source.toLowerCase().indexOf("<script");
        var s_e = source.indexOf(">", s);
        var e = source.toLowerCase().indexOf("</script", s);
        var e_e = source.indexOf(">", e);

        // Add to scripts array
        scripts.push(source.substring(s_e+1, e));
        // Strip from source
        source = source.substring(0, s) + source.substring(e_e+1);
    }

    // Loop through every script collected and eval it
    for(var i=0; i<scripts.length; i++) {
        try {
          if (scripts[i] != '')
          {         
            try  {          //IE
                  execScript(scripts[i]);   
      }
      catch(ex)           //Firefox
      {
        window.eval(scripts[i]);
      }   

            }  
        }
        catch(e) {
            // do what you want here when a script fails
         // window.alert('Script failed to run - '+scripts[i]);
          if (e instanceof SyntaxError) console.log (e.message+' - '+scripts[i]);
                    }
    }
// Return the cleaned source
    return source;
 }
函数解析脚本(\u源代码){
变量源=_源;
var scripts=newarray();
//去掉标签

while(source.toLowerCase().indexOf(“要做的另一件事是用脚本加载页面,例如:

<div id="content" onmouseover='myFunction();$(this).prop( 'onmouseover', null );'>
<script type="text/javascript">
function myFunction() {
  //do something
}
myFunction();
</script>
</div>

函数myFunction(){
//做点什么
}
myFunction();
这将加载页面,然后在函数运行后运行脚本并删除事件处理程序。这不会在ajax加载后立即运行,但如果您正在等待用户输入div元素,这将正常工作


PS.需要Jquery

这对我来说很有效,通过从ajax调用每个脚本内容的eval。完成:

$.ajax({}).done(function (data) {      
    $('div#content script').each(function (index, element) { eval(element.innerHTML); 
})  
注意:我没有将参数写入$.ajax,您必须对其进行调整 根据你的ajax


我的结论是HTML不允许嵌套的脚本标记。如果您使用javascript注入包含脚本标记的HTML代码,则不会起作用,因为javascript也包含在脚本标记中。您可以使用下一个代码测试它,您会发现它不起作用。用例是您使用AJAX或类似地,您得到的是HTML,并且希望直接将其注入HTMLDOM中。如果注入的HTML代码具有内部脚本标记,则无法工作

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body></body><script>document.getElementsByTagName("body")[0].innerHTML = "<script>console.log('hi there')</script>\n<div>hello world</div>\n"</script></html>
document.getElementsByTagName(“正文”)[0]。innerHTML=“console.log('hi there')\n Hello world\n”

如何加载div?取决于您使用的库,您通常可以控制是否只想在ajax加载后执行脚本。在
窗口之后。onload
我创建一个
XMTHttpRequest
对象来请求另一个(php)包含div内容的页面,包括一个脚本。我使用纯JS实现这一点,没有库(除了我自己的lol)使用jQuery的回调,我如何在新的中“执行”代码?我添加了一个使用成功回调的示例:非常感谢!myFunction();"部分原因是我在代码中遗漏了什么。如果你问我,这是一个比公认的答案好得多的答案。这几乎是JavaScript注入。虽然很有用,但这并不能回答为什么脚本不能运行的问题。例如,请看,它绝对应该运行,而我并没有找到一个简单的例子来说明它不起作用。@NaoISEOP实际上是在询问脚本执行情况,所以我认为这里没有问题。:-)不推荐使用Eval()。请看这一点-您可以选择所有加载的脚本并通过Eval()函数执行它们:
<div id="content" onmouseover='myFunction();$(this).prop( 'onmouseover', null );'>
<script type="text/javascript">
function myFunction() {
  //do something
}
myFunction();
</script>
</div>
$.ajax({}).done(function (data) {      
    $('div#content script').each(function (index, element) { eval(element.innerHTML); 
})  
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body></body><script>document.getElementsByTagName("body")[0].innerHTML = "<script>console.log('hi there')</script>\n<div>hello world</div>\n"</script></html>