摘要:五作用的關鍵方法,用來從目標節點克隆數據添加事件給克隆的元素注意采用數據分離的方法來保存上的事件和數據,利用標記每個元素,然后在內存上,將每個元素相關的數據放到內存中,然后在和內存的數據之間建立映射。
前言:這篇講完后,jQuery的文檔處理就告一段落了,有空我把這部分整合下,發一篇文章目錄。
一、示例代碼
jQuery源碼解析之clone() 這是divTwo 這是spanTwo
二、$().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()
作用:
設置目標元素內部的標簽為已執行
源碼:
//設置目標元素內部的`(完)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103852.html
摘要:一和的作用和區別觸發被選元素上的指定事件以及事件的默認行為比如表單提交不會引起事件比如表單提交的默認行為觸發所有匹配元素的指定事件只觸發第一個匹配元素的指定事件會冒泡不會冒泡二被點擊了作用看一源碼觸發事件,是自定義事件的額外參數源碼行解析本 showImg(https://segmentfault.com/img/remote/1460000019375685); 一、$().trig...
摘要:引用類型之所以會出現深淺拷貝的問題,實質上是由于對基本類型和引用類型的處理不同。另外方法可以視為數組對象的淺拷貝。上面描述過的復雜問題依然存在,可以說是最簡陋但是日常工作夠用的深拷貝方式。 一直想梳理下工作中經常會用到的深拷貝的內容,然而遍覽了許多的文章,卻發現對深拷貝并沒有一個通用的完美實現方式。因為對深拷貝的定義不同,實現時的edge case過多,在深拷貝的時候會出現循環引用等問...
摘要:根據項目選型決定是否開啟。為了壓縮,可維護為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調用的是這個原型實際上。功能檢測統一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數 jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...
摘要:根據項目選型決定是否開啟。為了壓縮,可維護為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調用的是這個原型實際上。功能檢測統一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數 jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...
閱讀 3503·2021-11-24 09:39
閱讀 781·2019-08-30 14:22
閱讀 3031·2019-08-30 13:13
閱讀 2310·2019-08-29 17:06
閱讀 2918·2019-08-29 16:22
閱讀 1255·2019-08-29 10:58
閱讀 2427·2019-08-26 13:47
閱讀 1628·2019-08-26 11:39