`
xhgrid
  • 浏览: 13808 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

执行AJAX返回HTML片段中的JavaScript脚本

阅读更多
如果AJAX加载的数据是一个HTML片段,而且这个HTML片段还包含脚本<script>块,那么在你把这数据xmlHttp.responseText用innerHTML方法插入到当前文档一个元素中,你会发现AJAX加载回来的脚本根本没有执行。这是AJAX开发中很常见的问题,如果你不是一直在用JavaScript框架做开发,相信你早就发现这个问题了。本文分析了两个解决办法,其中一个是讲解jQuery框架的实现。
一、 问题描述

下面举个简单的例子,演示问题所在。在下面的例子中,假设变量responseText就是AJAX加载的HTML片段数据,其中包含脚本弹出一条消息,用innerHTML方法插入ID为ajaxData的DIV中,你可能期望看到弹出那个消息框,结果你发现没有,问题就是这样。
<div id="ajaxData"></div>
<script type="text/javascript">
var responseText = '<p>这是一个段落</p><script>alert("这是AJAX加载回来的脚本片段")</script>';
document.getElementById('ajaxData').innerHTML = responseText;
</script>
二、两种解决办法

1、 利用JavaScript的eval方法执行脚本。

本方法的具体实现思路是把xmlHttp.responseText中的脚本都抽取出来,不管AJAX加载的HTML包含多少个脚本块,我们对找出来的脚本块都调用eval方法执行它即可。下面提供一个封装好的函数:
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

本方法的使用如下,对HTML用innerHTML方法添加到DOM,紧跟着调用executeScript方法执行脚本块:
document.getElementById("div1").innerHTML = xmlHttp.responseText;
executeScript(xmlHttp.responseText);

显然这个方法还是存在缺陷的,如果xmlHttp.responseText包含像这样的外部脚本调用:
<script type="text/javascript" src="/js/common.js"></script>,executeScript方法不能再深入执行这个外部加载的脚本。

2、 学习并使用jQuery框架的实现

jQuery对于AJAX加载HTML,是最终在执行html(value)方法时把整个xmlHttp.responseText数据转换成DOM,然后利用DOM相关操作方法来找出里面的脚本,最后再把这些脚本插入到head中。具体原理也不好说,先举个最简单的例子,然后再分析一下大致思路。先看例子:
$.get('ajax.aspx', function(data)
{
    $('#div1').html(data);
});

现在假设上面ajax.aspx页面返回的是HTML片段,而且包含一个或多个脚本块,甚至外部脚本引用。div1是AJAX请求发起页的一个DIV标签的ID,整句代码实现的结果是加载ajax.aspx中的HTML填充到一个ID为div1的DIV标签中。

在匿名回调函数中通过typeof(data)可以发现data还是原始的字符串,即等同于xmlHttp.responseText,通过代码执行跟踪发现,对AJAX加载脚本片段的执行处理不在jQuery的AJAX模块代码中,而是在html(value)方法,即把一段包含脚本块的HTML字符串插入DOM时,由它负责抽出脚本进行调用处理。而html(value)方法其实又是调用了append(value)方法……,整个过程大概调用了以下方法,箭头代表调用这些方法的先后顺序:

html -> append -> domManip -> clean -> evalScript -> globalEval

其中clean方法特别关键,这个方法也是jQuery比较重要的方法,其中也涉及修复HTML错误(标签没有结束,表格结构调整等方法)处理脚本。而脚本的抽出也是在这里进行的。看看相关源代码(jQuery1.3.2):
复制代码
if (fragment)
{
    for (var i = 0; ret[i]; i++)
    {
        if (jQuery.nodeName(ret[i], "script") && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript"))
        {
            scripts.push(ret[i].parentNode ? ret[i].parentNode.removeChild(ret[i]) : ret[i]);
        }
        else
        {
            if (ret[i].nodeType === 1)
                ret.splice.apply(ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))));
            fragment.appendChild(ret[i]);
        }
    }
    return scripts;
}
复制代码

另外,在evalScript方法中我们还发现如下代码,这里是“同”步加载像<script type="text/javascript" src="/js/common.js"></script>这样的外部脚本,解决executeScript方法存在的一个缺陷:
复制代码
if (elem.src)
    jQuery.ajax(
    {
        url: elem.src,
        async: false,
        dataType: "script"
    });
复制代码

同时也发现如下代码,这段代码是把xmlHttp.responseText中的脚本删除,因为在这个方法中,jQuery是准备把抽取的脚本放入head区,所以删除可以避免最终的HTML出现重复的脚本块:
if (elem.parentNode)
    elem.parentNode.removeChild(elem);

最后,在globalEval方法中,发现head.removeChild( script );方法,就是把脚本插入head后马上又移除脚本标签,这也是避免因为重复执行html(value)方法在head区生成重复的脚本块。这个移除是不影响脚本执行的,同是也是不会清除脚本块中的相关变量值。显然,如果你想看看html(data)最终的执行结果,比如抽取后插入到head的脚本块是什么,你可以先临时注释这一行代码。


作者:WebFlash
出处:http://webflash.cnblogs.com
分享到:
评论

相关推荐

    用AJAX返回HTML片段中的JavaScript脚本

    在下面的例子中,假设变量responseText就是AJAX加载的HTML片段数据,其中包含脚本弹出一条消息,用innerHTML方法插入ID为ajaxData的DIV中,你可能期望看到弹出那个消息框,结果你发现没有,问题就是这样。...

    jQuery+ajax实现动态执行脚本的方法

    向页面中注人脚本与加载HTML片段一样简单。但在这种情况下,需要使用全局函数 $.getScript(),这个全局函数与它的同辈函数类似,接受一个URL参数以查找脚本文件,参见如下代码: 代码如下:$(document).ready...

    toString()一个会自动调用的方法

    如果在你的WEB项目中,有很多地方都需要输出像下面这样的一个列表HTML: 代码如下: &lt;ul&gt; &lt;li&gt;JavaScript事件冒泡应用实例&lt;/li&gt; 执行AJAX返回HTML片段中的JavaScript脚本&lt;/li&gt; &lt;/ul&gt; 很显然这是一个LI结构,也许你...

    用ajax函数读取xml,然后解析XML.html.rar

    用ajax函数读取xml,然后解析XML.html,ajax无刷新读取文件,先使用jQuery加载XML,然后建立一个代码片段,遍历所有student节点,获取id节点,获取节点文本,获取student下的email属性,构造HTML字符串,通过append...

    Json、Webservice、Jquery、Ajax

    Scripts\ 常用javascript脚本文件夹 jquery-1.4.1-vsdoc.js jquery智能感知引用 jquery-1.4.1.js jquery一用文件 jquery-1.4.1.min.js jquery精简版 Styles\ 样式文件夹 Site.css 样式文件 ...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part1.rar

     1.3 JavaScript语法中常见的陷阱   1.3.1 区分大小写   1.3.2 单引号与双引号   1.3.3 换行   1.3.4 可选的分号和花括号   1.3.5 重载(并非真正的重载)   1.3.6 匿名函数   1.3.7 作用域...

    十个优秀的Ajax/Javascript实例网站收集

    1.Ajax Rain    AjaxRain有很多完美整合AJAX, CSS, DHTML 或 Javascript的实例...MiniAJAX 是一个新生的网站,收集了少许 DHTML 和 AJAX 脚本, 它的代码片段风格非常实用。 4.Ajaxian    一个接近于门户类型的AJAX

    grimoire:片段、脚本和咒语的集合

    一组有用的脚本、片段和咒语,使互联网变得更美好。 目录结构 javascript ajax_post : 使用 ajax 发布到 PHP 文件(XMLHttpRequest 对象返回数据) button_marker : 动画菜单按钮标记 countdown_timer : 倒计时...

    Ajax并不神秘:揭下各种Ajax控件和类库的小裤衩

    Ajax控件和类库现在真的太多了,不知不觉中增加了Ajax的神秘性和复杂...这段文本可以是xml格式,也可以是一个Html片段,也可以是一段JavaScript脚本,或者仅是一个字符串。服务器端仅仅是作为一个数据接口,客户端使用

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part3.rar

     1.3 JavaScript语法中常见的陷阱   1.3.1 区分大小写   1.3.2 单引号与双引号   1.3.3 换行   1.3.4 可选的分号和花括号   1.3.5 重载(并非真正的重载)   1.3.6 匿名函数   1.3.7 作用域...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版.part2.rar

     1.3 JavaScript语法中常见的陷阱   1.3.1 区分大小写   1.3.2 单引号与双引号   1.3.3 换行   1.3.4 可选的分号和花括号   1.3.5 重载(并非真正的重载)   1.3.6 匿名函数   1.3.7 作用域...

    用ajax函数读取xml,然后解析XML.html

    摘要:脚本资源,Ajax/JavaScript,ajax无刷新读取文件 用ajax函数读取xml,然后解析XML.html,ajax无刷新读取文件,先使用jQuery加载XML,然后建立一个代码片段,遍历所有student节点,获取id节点,获取节点文本,获取...

    qunit-fixtures-loader:加载要在QUnit测试中使用HTML片段

    成功完成所有请求后,将从每个ajax结果中提取HTML响应,并将其作为参数传递给解析,并以与给定url相同的顺序返回给调用方。用法使用插件相当容易。 给定经典的QUnit测试设置,我们需要添加脚本以在测试HTML设置中...

    最新JQuery版本1.8

    “$.parseHTML”也提供了一种方式将HTML解析为DOM片段,并控制可能包含的任何脚本的执行。这对于由Content Security Policy (CSP)控制的JavaScript环境来说特别重要,因为注入的脚本可能导致安全警告或异常。 在...

    最新jquery.1.8.1

    “$.parseHTML”也提供了一种方式将HTML解析为DOM片段,并控制可能包含的任何脚本的执行。这对于由Content Security Policy (CSP)控制的JavaScript环境来说特别重要,因为注入的脚本可能导致安全警告或异常。 在...

    html入门到放弃笔记

    HTML中用于描述功能的符号称为"标记" 标记在使用时,用尖括号 "&lt;&gt;",标记的分类 1、封闭类型的标记 也称为 "双标记" , 必须成对出现 语法:&lt;标记&gt;内容标记&gt; Demo : 1、创建 p 标记 --&lt;p&gt;...&lt;/p&gt; 2、创建 ...

    Sublime2_Snippets_ServiceNow_Glide:适用于ServiceNow的Sublime 2代码片段Glide Ajax,客户端,表单和服务器

    ServiceNow-语法编辑器宏:vargr JavaScript执行编辑器:在表单中,按启动Javascript Executor JavaScript Log&Field Watcher 我们想要什么:精明的UI编辑器Intellisense自动完成推荐工具:Sublime 2编辑器-用于对...

    高性能网站建设指南2 中文版 高性能网站建设指南(中文版)

     《高性能网站建设指南》一书介绍了如何针对网站中的Ajax、CSS、JavaScript、Flash和图片进行性能优化。每个性能规则都提供了示例,在本书的配套网站上可以找到代码片段。这些规则包括:  •减少HTTP请求 •使用...

Global site tag (gtag.js) - Google Analytics