摘要:五作用的關(guān)鍵方法,用來(lái)從目標(biāo)節(jié)點(diǎn)克隆數(shù)據(jù)添加事件給克隆的元素注意采用數(shù)據(jù)分離的方法來(lái)保存上的事件和數(shù)據(jù),利用標(biāo)記每個(gè)元素,然后在內(nèi)存上,將每個(gè)元素相關(guān)的數(shù)據(jù)放到內(nèi)存中,然后在和內(nèi)存的數(shù)據(jù)之間建立映射。
前言:這篇講完后,jQuery的文檔處理就告一段落了,有空我把這部分整合下,發(fā)一篇文章目錄。
一、示例代碼
jQuery源碼解析之clone() 這是divTwo 這是spanTwo
二、$().clone()
作用:
生成被選元素的副本,包含子節(jié)點(diǎn)、文本和屬性
注意:
$("div").clone(true) 表示克隆目標(biāo)節(jié)點(diǎn)的事件和數(shù)據(jù)
$("div").clone(true,true) 表示克隆目標(biāo)節(jié)點(diǎn)及其子節(jié)點(diǎn)的事件和數(shù)據(jù)
源碼:
jQuery.fn.extend({ //克隆目標(biāo)節(jié)點(diǎn)及其子節(jié)點(diǎn) //dataAndEvents是否克隆目標(biāo)節(jié)點(diǎn)的事件和數(shù)據(jù),默認(rèn)是false //deepDataAndEvents是否克隆目標(biāo)節(jié)點(diǎn)子節(jié)點(diǎn)的事件和數(shù)據(jù),默認(rèn)值是dataAndEvents //源碼6327行 clone: function( dataAndEvents, deepDataAndEvents ) { //默認(rèn)是false dataAndEvents = dataAndEvents == null ? false : dataAndEvents; //默認(rèn)是dataAndEvents deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; //循環(huán)調(diào)用jQuery.clone return this.map( function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); } ); }, });
解析:
可以看到,這里還是比較簡(jiǎn)單的,需要注意的就是參數(shù)deepDataAndEvents不填的話,其值是根據(jù)參數(shù)dataAndEvents的值來(lái)定的
三、jQuery.clone()
作用同上
源碼:
jQuery.extend( { //源碼6117行 //生成被選元素的副本,包含子節(jié)點(diǎn)、文本和屬性 clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, //拷貝目標(biāo)節(jié)點(diǎn)的屬性和值 //如果為true,則包括拷貝子節(jié)點(diǎn)的所有屬性和值 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 //從目標(biāo)節(jié)點(diǎn)克隆事件,并綁定給克隆的元素 if ( dataAndEvents ) { //克隆子節(jié)點(diǎn)的事件和數(shù)據(jù) if ( deepDataAndEvents ) { //源節(jié)點(diǎn) srcElements = srcElements || getAll( elem ); //克隆節(jié)點(diǎn) destElements = destElements || getAll( clone ); for ( i = 0, l = srcElements.length; i < l; i++ ) { cloneCopyEvent( srcElements[ i ], destElements[ i ] ); } } //只克隆目標(biāo)節(jié)點(diǎn)和數(shù)據(jù) else { cloneCopyEvent( elem, clone ); } } //將script標(biāo)簽設(shè)為已運(yùn)行 // 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()方法上進(jìn)行處理
(2)從目標(biāo)節(jié)點(diǎn)克隆數(shù)據(jù)、添加事件給克隆的元素
(3)將克隆的元素中的script標(biāo)簽設(shè)為已運(yùn)行
四、fixInput()
作用:
(1)解決 IE 無(wú)法保存克隆的單選、多選的狀態(tài)的 bug
(2)解決 IE 無(wú)法將克隆的選項(xiàng)返回至默認(rèn)選項(xiàng)狀態(tài)的 bug
源碼:
//解決IE的bug:(1)無(wú)法保存克隆的單選、多選的狀態(tài) (2)無(wú)法將克隆的選項(xiàng)返回至默認(rèn)選項(xiàng)狀態(tài) // 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無(wú)法保存克隆的單選框和多選框的選擇狀態(tài) if ( nodeName === "input" && rcheckableType.test( src.type ) ) { dest.checked = src.checked; } //IE無(wú)法將克隆的選項(xiàng)返回至默認(rèn)選項(xiàng)狀態(tài) // Fails to return the selected option to the default selected state when cloning options else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; } }
解析:
本質(zhì)就是將目標(biāo)元素的checked屬性和defaultValue屬性手動(dòng)賦值給克隆的元素。
五、cloneCopyEvent()
作用:
$().clone()的關(guān)鍵方法,用來(lái)從目標(biāo)節(jié)點(diǎn)克隆數(shù)據(jù)、添加事件給克隆的元素
注意:
jQuery 采用數(shù)據(jù)分離的方法來(lái)保存 DOM 上的事件和數(shù)據(jù),利用 uuid 標(biāo)記每個(gè) DOM 元素,然后在內(nèi)存上,將每個(gè) DOM 元素相關(guān)的數(shù)據(jù)放到內(nèi)存中,然后在 uuid 和內(nèi)存的數(shù)據(jù)之間建立映射。
優(yōu)點(diǎn)是方便復(fù)制數(shù)據(jù)。
注意:事件是不可賦值的,只能一個(gè)個(gè)添加!
示意圖:
源碼:
//src:目標(biāo)元素 //dest:克隆的元素 //源碼5902行 function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; } //拷貝jQuery內(nèi)部數(shù)據(jù):事件、處理程序等 // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { //private data old,即目標(biāo)元素的數(shù)據(jù) //注意:jQuery是通過(guò)uuid將目標(biāo)元素進(jìn)行標(biāo)記, //然后將與目標(biāo)元素相關(guān)的數(shù)據(jù)都放到內(nèi)存中 //通過(guò)uuid和內(nèi)存的數(shù)據(jù)建立映射 //這種數(shù)據(jù)分離的做法有利于復(fù)制數(shù)據(jù),但不能復(fù)制事件 pdataOld = dataPriv.access( src ); //private data current,即為克隆的元素設(shè)置數(shù)據(jù) pdataCur = dataPriv.set( dest, pdataOld ); events = pdataOld.events; //如果事件存在 if ( events ) { //移除克隆對(duì)的元素的處理程序和事件 delete pdataCur.handle; pdataCur.events = {}; //依次為克隆的元素添加事件 //注意:事件是不能被復(fù)制的,所以需要重新綁定 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 //拷貝用戶數(shù)據(jù) if ( dataUser.hasData( src ) ) { udataOld = dataUser.access( src ); udataCur = jQuery.extend( {}, udataOld ); //為克隆的元素設(shè)置數(shù)據(jù) dataUser.set( dest, udataCur ); } }
解析:
(1)拷貝 jQuery 內(nèi)部數(shù)據(jù)(事件、處理程序)
拷貝賦值數(shù)據(jù):
pdataOld = dataPriv.access( src ); //private data current,即為克隆的元素設(shè)置數(shù)據(jù) pdataCur = dataPriv.set( dest, pdataOld );
拷貝添加事件:
jQuery.event.add( dest, type, events[ type ][ i ] );
(2)拷貝用戶數(shù)據(jù)
dataUser.set( dest, udataCur );
六、setGlobalEval()
作用:
設(shè)置目標(biāo)元素內(nèi)部的標(biāo)簽為已執(zhí)行
源碼:
//設(shè)置目標(biāo)元素內(nèi)部的`(完)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/103852.html
摘要:一和的作用和區(qū)別觸發(fā)被選元素上的指定事件以及事件的默認(rèn)行為比如表單提交不會(huì)引起事件比如表單提交的默認(rèn)行為觸發(fā)所有匹配元素的指定事件只觸發(fā)第一個(gè)匹配元素的指定事件會(huì)冒泡不會(huì)冒泡二被點(diǎn)擊了作用看一源碼觸發(fā)事件,是自定義事件的額外參數(shù)源碼行解析本 showImg(https://segmentfault.com/img/remote/1460000019375685); 一、$().trig...
摘要:引用類(lèi)型之所以會(huì)出現(xiàn)深淺拷貝的問(wèn)題,實(shí)質(zhì)上是由于對(duì)基本類(lèi)型和引用類(lèi)型的處理不同。另外方法可以視為數(shù)組對(duì)象的淺拷貝。上面描述過(guò)的復(fù)雜問(wèn)題依然存在,可以說(shuō)是最簡(jiǎn)陋但是日常工作夠用的深拷貝方式。 一直想梳理下工作中經(jīng)常會(huì)用到的深拷貝的內(nèi)容,然而遍覽了許多的文章,卻發(fā)現(xiàn)對(duì)深拷貝并沒(méi)有一個(gè)通用的完美實(shí)現(xiàn)方式。因?yàn)閷?duì)深拷貝的定義不同,實(shí)現(xiàn)時(shí)的edge case過(guò)多,在深拷貝的時(shí)候會(huì)出現(xiàn)循環(huán)引用等問(wèn)...
摘要:根據(jù)項(xiàng)目選型決定是否開(kāi)啟。為了壓縮,可維護(hù)為了支持從而使用代替變量存儲(chǔ)防沖突會(huì)用到,形如版本號(hào)聲明最終調(diào)用的是這個(gè)原型實(shí)際上。功能檢測(cè)統(tǒng)一兼容性問(wèn)題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對(duì)象添加一些方法和屬性; (285 , 347) ...
摘要:根據(jù)項(xiàng)目選型決定是否開(kāi)啟。為了壓縮,可維護(hù)為了支持從而使用代替變量存儲(chǔ)防沖突會(huì)用到,形如版本號(hào)聲明最終調(diào)用的是這個(gè)原型實(shí)際上。功能檢測(cè)統(tǒng)一兼容性問(wèn)題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對(duì)象添加一些方法和屬性; (285 , 347) ...
閱讀 3730·2021-11-24 09:39
閱讀 852·2019-08-30 14:22
閱讀 3095·2019-08-30 13:13
閱讀 2396·2019-08-29 17:06
閱讀 3027·2019-08-29 16:22
閱讀 1324·2019-08-29 10:58
閱讀 2511·2019-08-26 13:47
閱讀 1697·2019-08-26 11:39