博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JQuery html API支持解析执行Javascript脚本功能实现-代码分析
阅读量:5890 次
发布时间:2019-06-19

本文共 4854 字,大约阅读时间需要 16 分钟。

JQuery html用法(功能类似innerHTML)

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

                          
hello world!

 

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

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

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

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

 

代码例子:

        

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 functionvar 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>
" ) + 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执行。

        

 

转载地址:http://njfsx.baihongyu.com/

你可能感兴趣的文章
Windows Phone 7 框架和页面
查看>>
Directx11教程(31) 纹理映射(1)
查看>>
Android——Button的颜色
查看>>
创建ITS mobile 应用程序步骤
查看>>
《星辰傀儡线》人物续:“灭世者”、“疯狂者”、“叛逆者”三兄妹
查看>>
安装系统字体
查看>>
Spring的ApplicationContext加载备忘
查看>>
GoogleMapAPIV3.8.6离线包下载
查看>>
SILK 的 Tilt的意思
查看>>
IPC通信:Posix共享内存2
查看>>
GB2312转成UTF-8
查看>>
C#打开chm定位到特定页面
查看>>
[CareerCup][Google Interview] 寻找动态的中位数
查看>>
javascript操作iframe的那些事
查看>>
servlet相关 jar包位置 BAE上部署web应用
查看>>
路徑 z
查看>>
cpu分析简介
查看>>
1.备忘录模式
查看>>
Html学习笔记3
查看>>
杭州见闻
查看>>