今天是第四天啦!笔记的内容主要是跟着慕课网上的jQuery源码解析系列课程以及本身的理解+实践来写的(也比较偏向于本身的梳理,因此可能会有点乱),可能会有错误,欢迎指出。node
原生的cloneNode不会复制js属性(好比:事件),可是IE会复制事件处理程序。浏览器
cloneNode(isDeep)
isDeep接受一个参数,true表示执行深拷贝,复制文本以及它的子节点树。false表示只复制节点自己。缓存
IE低版本会克隆原生事件,但2.1.1版本不处理兼容低级版本。dom
数据缓存机制:
jQuery遍历节点clone的时候,把事件和数据一并复制。
jQuery在DOM上作了一个uuid的标记,把这个dom关联的数据放在一个内存区域,经过uuid进行映射,可是事件须要从新绑定。ui
jQuery的clone()源码:lua
clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, //克隆原节点 clone = elem.cloneNode( true ), //判断是否是文档节点 inPage = jQuery.contains( elem.ownerDocument, elem ); //浏览器单选框选中状态不能正确克隆且该elem是元素或者文档碎片,但不是XML文档的 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { //就进行选择状态处理(fixInput见下) for ( i = 0, l = srcElements.length; i < l; i++ ) { fixInput( srcElements[ i ], destElements[ i ] ); } } // 添加事件 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 ); } } // Preserve script evaluation history destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } // Return the cloned set return clone; }
fixInput用来处理input元素:code
function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); //若是元素是可check的input元素 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { //把选中的状态也复制过去 dest.checked = src.checked; } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } }
复制事件:对象
function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; //若是目标对象不是元素直接返回 if ( dest.nodeType !== 1 ) { return; } // 1. 复制data_priv: events, handlers等 if ( data_priv.hasData( src ) ) { //获取源元素的data_privv pdataOld = data_priv.access( src ); //set方法返回的是cache pdataCur = data_priv.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. 复制data_user if ( data_user.hasData( src ) ) { udataOld = data_user.access( src ); udataCur = jQuery.extend( {}, udataOld ); data_user.set( dest, udataCur ); } }
更加详细的状况之后确定会再次碰到和了解( •̀ ω •́ )今天就先在这里。接口