今天是第四天啦!筆記的內容主要是跟着慕課網上的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 ); } }
更加詳細的狀況之後確定會再次碰到和了解( •̀ ω •́ )今天就先在這裏。接口