JQuery html用法(功能类似innerHTML)

开发中需要使用Ajax技术来更新页面局部区域, 使用的方法是ajax获取html代码段(字符串),然后将这个html代码段作为参数,传入目标DOM(JQuery对象)的JQuery html接口,此语句执行后, 会将html代码段解释执行, 显示出html代码段描述的页面控件。 例如:

<html>
<head>
<script type="text/javascript" src="./jquery.js"></script>
<style> </style>
</head>
<body>
<div>hello world!</div>
<script type='text/javascript'>
//假设ajaxHTMLStr是通过ajax获得的html代码段
var ajaxHTMLStr = "<input type='button' value='click me'>";
$("div").html(ajaxHTMLStr);
</script>
</body>
</html>

JQuery html可以解析执行js脚本,为啥?

  html接口对于入参内容的要求,可以包括html标签代码,也可以包括Javascript代码段(使用 <script>标签括起来的部分),执行的效果是, html标签可以显示, 同时Javascript代码可以被执行, 这个是为什么? 是通过什么方式实现?

  通过js原生的innerHTML属性设置包括js代码段字符串,js代码不能执行。原生js接口中只能通过 eval 来执行js代码,猜测html的实现最终是调用这个函数来执行。先通过JQuery解析出js代码段中的文本信息,然后执行。

  测试JQuery append添加包括js代码段的字符串,js也可以被执行。

代码例子:

<html>
<head>
<script src="./jquery.js"></script>
</head>
<body>
<div name="template">
<select>
</select>
<input type="button" name="testBtn" value="click me">
</div>
<script>
var divhtml = "<script type='text\/javascript'>console.log('aa')<\/script>";
divhtml += "<div>aa</div>"; //只能执行html段, javascript代码段忽略
//$("[name='template']").get(0).innerHTML = divhtml; //能执行html, javascript代码
$("[name='template']").eq(0).html(divhtml); //能执行html, javascript代码
//$("[name='template']").eq(0).append(divhtml);
</script>
</body>
</html>

JQuery实现html接口解析执行js脚本 - 关键代码分析

查看jquery源代码,分析html接口相关实现

1、 html 接口实际上是, 将入参value传递到 access 接口中, 直接调用access, access的返回值就是 html的返回值。

    html: function( value ) {
return access( this, function( value ) {
.......
}, null, value, arguments.length );

2、 access 函数分析

此函数为多功能函数, 由入参决定实现的功能, 其他api如 text css attr 都是调用此接口实现,

主要作用为, 将入参fn(一个函数)作用到elems上执行, key和value都可以作为fn执行的入参, 返回值还是elems。

// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {

对于html接口设置html代码段字符串情况,access中执行代码, 会将fn作用到elems上,并带着入参value, 如下代码,

        if ( bulk ) {
// Bulk operations run against the entire set
if ( raw ) {
fn.call( elems, value );
fn = null;

返回elems:

    return chainable ?
elems
: // Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet; return chainable ?
elems : // Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet;

3、 下面看看 html 接口调用access时候,实现的fn函数

当html如参为空, 则表示获取dom内的html代码:

            if ( value === undefined ) {
return elem.nodeType === 1 ?
elem.innerHTML.replace( rinlinejQuery, "" ) :
undefined;
}

判断html代码段中, 没有script link 和 style, 则表示为纯html标签代码,使用innerHTML直接更新文档:

            // See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
。。。。
elem.innerHTML = value;
。。。。

如果非上面两种情况, 则调用empty和append接口(也是JQuery API), 将html代码段更新到文档:

            if ( elem ) {
this.empty().append( value );
}

empty实现不为我们关注, 下面我们重点关注append实现关于js代码执行的关系。

4、 append函数分析

append实现,直接调用 domManip 函数, 将append的入参作为domManip函数的第一个参数, 将一个回调函数作为第二个参数, 最后返回其返回值。

    append: function() {
return this.domManip( arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.appendChild( elem );
}
});
},

5、domManip实现分析

首先,调用buildFragment,将arguments(html代码段字符串)传入构造一个 fragment DOM对象,此对象脱离文档流,仅仅存在于内存中。

        if ( l ) {
fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
first = fragment.firstChild;
    buildFragment: function( elems, context, scripts, selection ) {
。。。
safe = createSafeFragment( context ),
。。。
return safe;
},
createSafeFragment
function createSafeFragment( document ) {
var list = nodeNames.split( "|" ),
safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) {
while ( list.length ) {
safeFrag.createElement(
list.pop()
);
}
}
return safeFrag;
}
其次此函数将html代码转换为dom
                // Convert html into DOM nodes
} else {
tmp = tmp || safe.appendChild( context.createElement("div") ); // Deserialize a standard representation
tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
wrap = wrapMap[ tag ] || wrapMap._default; tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
然后此函数将 script dom节点的text内容拿去eval计算一下,支持科理解此问题的原因了
                            if ( node.src ) {
// Optional AJAX dependency, but won't run scripts if not present
if ( jQuery._evalUrl ) {
jQuery._evalUrl( node.src );
}
} else {
jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
}

总结 jquery html执行js的原理

使用innerHTML将 html代码段(包括 html标签字符串 和 js代码段字符串)加入到DOM树中,  然后获取js的script节点的内容,调用eval执行。

<html>
<head>
<script src="./jquery.js"></script>
</head>
<body>
<div name="template">
<select>
</select>
<input type="button" name="testBtn" value="click me">
</div>
<script>
var divhtml = "<script type='text\/javascript'>console.log('aa')<\/script>";
divhtml += "<div>aa</div>"; //只能执行html段, javascript代码段忽略
$("[name='template']").get(0).innerHTML = divhtml; //脚本虽然没有被执行,但是仍然被加入到DOM树中, 可以获取脚本内容执行
var scriptDOM = $("script", "[name='template']");
console.log("nodeType="+scriptDOM.get(0).nodeType);
var scriptStr = scriptDOM.text();
console.log("script code="+scriptStr);
eval(scriptStr); //能执行html, javascript代码
//$("[name='template']").eq(0).html(divhtml); //能执行html, javascript代码
//$("[name='template']").eq(0).append(divhtml); </script>
</body>
</html>

JQuery html API支持解析执行Javascript脚本功能实现-代码分析的更多相关文章

  1. Selenium执行JavaScript脚本

    JavaScript是运行在客户端(浏览器)和服务器端的脚本语言,允许将静态网页转换为交互式网页.可以通过 Python Selenium WebDriver 执行 JavaScript 语句,在We ...

  2. 在WebBrowser中执行javascript脚本的几种方法整理(execScript/InvokeScript/NavigateScript) 附完整源码

    [实例简介] 涵盖了几种常用的 webBrowser执行javascript的方法,详见示例截图以及代码 [实例截图] [核心代码] execScript方式: 1 2 3 4 5 6 7 8 9 1 ...

  3. Java执行JavaScript脚本破解encodeInp()加密

    一:背景 在模拟登录某网站时遇到了用户名和密码被JS进行加密提交的问题,如图: 二:解决方法 1.我们首先需要获得该JS加密函数,一般如下: conwork.js var keyStr = " ...

  4. 【Android】不使用WebView来执行Javascript脚本(Rhino)

    前言 动态执行脚本能有效的降低重要功能硬编码带来的问题,尤其是依赖于第三方的应用,可以通过动态脚本+在线参数(例如友盟在线参数)再不更新应用的情况下升级功能. 声明 欢迎转载,但请保留文章原始出处:) ...

  5. Python爬虫(二十四)_selenium案例:执行javascript脚本

    本章叫介绍如何使用selenium在浏览器中使用js脚本,更多内容请参考:Python学习指南 隐藏百度图片 #-*- coding:utf-8 -*- #本篇将模拟执行javascript语句 fr ...

  6. svn利用钩子脚本功能实现代码同步到web目录

    一.hook简单介绍 为了方便管理员控制提交的过程 ,Subversion提供了hook机制.当特定的 事件发生时,相应的 hook会被调用,hook其实就相当于特定事件的处理函数.每个hook会得到 ...

  7. HtmlUnit+Jsoup 解决爬虫无法解析执行javascript的问题

    本人最近在研究爬虫.作为一个新手.研究了些爬虫框架,发现所有开源的爬虫框架很多,功能也很齐全,但唯独遗憾的是,目前还没有发现那个爬虫对js完美的解释并执行.看了浅谈网络爬虫爬js动态加载网页(二)之后 ...

  8. IOS中UIWebView执行javaScript脚本时注意点

    1.webView之所以能够滚动,因为它内部有一个UIScrollView子控件 2.移除webView顶部和底部灰色的一层view * 遍历webView中scrollView内部的所有子控件 * ...

  9. 基于Selenium2+Java的UI自动化(5) - 执行JavaScript脚本

    一.操作日期选择框 QQ图片20161118215530.png1336x545 22.6 KB 说明:日期选择框大部分是不支持前端输入的,因为这个对象是 readOnly,只读属性,selenium ...

随机推荐

  1. 20145304 刘钦令 Java程序设计第二周学习总结

    20145304 <Java程序设计>第2周学习总结 教材学习内容总结 java可区分基本类型和类类型(即参考类型)两大类型系统. 基本类型主要可区分为整数.字节.浮点数.字符与布尔. 整 ...

  2. xenu工具介绍

    Xenu Link Sleuth 也许是你所见过的最小但功能最强大的检查网站死链接的软件了.你可以打开一个本地网页文件来检查它的链接,也可以输入任何网址来检查.它可以分别列出网站 的活链接以及死链接, ...

  3. 【COGS】894. 追查坏牛奶

    http://cojs.tk/cogs/problem/problem.php?pid=894 题意:n个点m条边的加权网络,求最少边数的按编号字典序最小的最小割.(n<=32, m<=1 ...

  4. Linux常见练习题

    1./dev/hda5在Linux中表示什么? A. IDE0接口上从盘       B. IDE0接口上主盘的逻辑分区 C. IDE0接口上主盘的第五个分区    D.IDE0接口上从盘的扩展分区  ...

  5. java代码过滤emoji表情

    可以新建一个过滤器的类,在类中书写如下代码: public static String filterEmoji(String source) {           if(source != null ...

  6. Linux进程间通信:IPC对象——信号灯集详解

    作者:倪老师,华清远见嵌入式学院讲师. 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制.相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时 ...

  7. Daily Scrum 10.24

    昨天我们的工作已经全面开始了,本来想等今天(25号)看那个燃尽图和燃速图能不能出来,结果还是没有,就先把我们的Task统计贴上来吧. 今天的Task统计: 至于燃尽图和燃速图的问题已经发老师邮件提问了 ...

  8. sql 数据库 初级 个人学习总结(一)

    数据库个人总结(初级)1.增删改查 insert into 表名 values ('条件','条件2') delete from 表名 where 条件 update 表名 set=条件值 where ...

  9. js 日期

    let date = new Date(); let year = date.getFullYear(); let money = money = date.getMonth() + 1; let d ...

  10. 如何在maven工程中加载oracle驱动

    maven中引入oracle驱动报错Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0 时间:2015年09月22日  浏览:9361次 在maven ...