内容简介:前言:这篇讲完后,jQuery的二、
前言:这篇讲完后,jQuery的 文档处理
就告一段落了,有空我把这部分整合下,发一篇文章目录。
一、示例代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jQuery源码解析之clone()</title> </head> <body> <script src="jQuery.js"></script> <div id="divTwo"> <p id="pTwo">这是divTwo <span id="spanTwo">这是spanTwo</span> </p> </div> <div id="divOne"> </div> <script> $("#pTwo").click(function () { alert("pTwo被点击了") }) $("#spanTwo").click(function (e) { //阻止冒泡 e.stopPropagation() alert("spanTwo被点击了") }) // $("#pTwo").clone().appendTo($("#divOne")) // $("#pTwo").clone(true,false).appendTo($("#divOne")) $("#pTwo").clone(true,true).appendTo($("#divOne")) </script> </body> </html>
二、 $()
.clone()
作用:
生成被选元素的副本,包含子节点、文本和属性
注意:
$('div')
.clone(
true
) 表示克隆目标节点的
事件和数据
$('div')
.clone( true,true
) 表示克隆目标节点及其子节点的 事件和数据
源码:
jQuery.fn.extend({ //克隆目标节点及其子节点 //dataAndEvents是否克隆目标节点的事件和数据,默认是false //deepDataAndEvents是否克隆目标节点子节点的事件和数据,默认值是dataAndEvents //源码6327行 clone: function( dataAndEvents, deepDataAndEvents ) { //默认是false dataAndEvents = dataAndEvents == null ? false : dataAndEvents; //默认是dataAndEvents deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; //循环调用jQuery.clone return this.map( function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); } ); }, });
解析:
可以看到,这里还是比较简单的,需要注意的就是 参数deepDataAndEvents
不填的话,其值是根据 参数dataAndEvents
的值来定的
三、jQuery.clone()
作用同上
源码:
jQuery.extend( { //源码6117行 //生成被选元素的副本,包含子节点、文本和属性 clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, //拷贝目标节点的属性和值 //如果为true,则包括拷贝子节点的所有属性和值 clone = elem.cloneNode( true ), //判断elem是否脱离文档流 inPage = jQuery.contains( elem.ownerDocument, elem ); // Fix IE cloning issues //兼容性处理,解决IE bug if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); for ( i = 0, l = srcElements.length; i < l; i++ ) { fixInput( srcElements[ i ], destElements[ i ] ); } } // Copy the events from the original to the clone //从目标节点克隆事件,并绑定给克隆的元素 if ( dataAndEvents ) { //克隆子节点的事件和数据 if ( deepDataAndEvents ) { //源节点 srcElements = srcElements || getAll( elem ); //克隆节点 destElements = destElements || getAll( clone ); for ( i = 0, l = srcElements.length; i < l; i++ ) { cloneCopyEvent( srcElements[ i ], destElements[ i ] ); } } //只克隆目标节点和数据 else { cloneCopyEvent( elem, clone ); } } //将script标签设为已运行 // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } // Return the cloned set return clone; }, })
解析:
可以看到这部分源码主要分为三大块:
(1)解决 IE 的 bug,主要是在 fixInput()
方法上进行处理
(2)从目标节点克隆数据、添加事件给克隆的元素
(3)将克隆的元素中的script标签设为已运行
四、fixInput()
作用:
(1)解决 IE 无法保存克隆的单选、多选的状态的 bug
(2)解决 IE 无法将克隆的选项返回至默认选项状态的 bug
源码:
//解决IE的bug:(1)无法保存克隆的单选、多选的状态 (2)无法将克隆的选项返回至默认选项状态 // Fix IE bugs, see support tests //源码5937行 function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); // Fails to persist the checked state of a cloned checkbox or radio button. //IE无法保存克隆的单选框和多选框的选择状态 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { dest.checked = src.checked; } //IE无法将克隆的选项返回至默认选项状态 // Fails to return the selected option to the default selected state when cloning options else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } }
解析:
本质就是将目标元素的 checked属性
和 defaultValue属性
手动赋值给克隆的元素。
五、cloneCopyEvent()
作用:
$().clone()
的关键方法,用来从目标节点克隆数据、添加事件给克隆的元素
注意:
jQuery 采用数据分离的方法来保存 DOM 上的事件和数据,利用 uuid 标记每个 DOM 元素,然后在内存上,将每个 DOM 元素相关的数据放到内存中,然后在 uuid 和内存的数据之间建立映射。
优点是方便复制数据。
注意:事件是不可赋值的,只能一个个添加!
示意图:
源码:
//src:目标元素 //dest:克隆的元素 //源码5902行 function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; } //拷贝jQuery内部数据:事件、处理程序等 // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { //private data old,即目标元素的数据 //注意:jQuery是通过uuid将目标元素进行标记, //然后将与目标元素相关的数据都放到内存中 //通过uuid和内存的数据建立映射 //这种数据分离的做法有利于复制数据,但不能复制事件 pdataOld = dataPriv.access( src ); //private data current,即为克隆的元素设置数据 pdataCur = dataPriv.set( dest, pdataOld ); events = pdataOld.events; //如果事件存在 if ( events ) { //移除克隆对的元素的处理程序和事件 delete pdataCur.handle; pdataCur.events = {}; //依次为克隆的元素添加事件 //注意:事件是不能被复制的,所以需要重新绑定 for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } } // 2. Copy user data //拷贝用户数据 if ( dataUser.hasData( src ) ) { udataOld = dataUser.access( src ); udataCur = jQuery.extend( {}, udataOld ); //为克隆的元素设置数据 dataUser.set( dest, udataCur ); } }
解析:
(1)拷贝 jQuery 内部数据(事件、处理程序)
拷贝赋值数据:
pdataOld = dataPriv.access( src ); //private data current,即为克隆的元素设置数据 pdataCur = dataPriv.set( dest, pdataOld );
拷贝添加事件:
jQuery.event.add( dest, type, events[ type ][ i ] );
(2)拷贝用户数据
dataUser.set( dest, udataCur );
六、setGlobalEval()
作用:
设置目标元素内部的 <script>
标签为已执行
源码:
//设置目标元素内部的`<script>`标签为已执行 //源码4934行 // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { var i = 0, l = elems.length; for ( ; i < l; i++ ) { dataPriv.set( elems[ i ], "globalEval", !refElements || dataPriv.get( refElements[ i ], "globalEval" ) ); } }
(完)
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- ReactNative源码解析-初识源码
- Spring源码系列:BeanDefinition源码解析
- Spring源码分析:AOP源码解析(下篇)
- Spring源码分析:AOP源码解析(上篇)
- 注册中心 Eureka 源码解析 —— EndPoint 与 解析器
- 新一代Json解析库Moshi源码解析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP和MySQL Web开发
Luke Welling、Laura Thomson / 武欣、邵煜 / 机械工业出版社 / 2005-12 / 78.00元
本书将PHP开发与MySQL应用相结合,分别对PHP和MySQL做了深入浅出的分析,不仅介绍PHP和MySQL的一般概念,而且对PHP和MySQL的Web应用做了较全面的阐述,并包括几个经典且实用的例子。一起来看看 《PHP和MySQL Web开发》 这本书的介绍吧!