什么情況下使用到克隆節(jié)點?
我們知道在對DOM操作過程中如果直接使用節(jié)點會出現(xiàn)節(jié)點隨操作而變動的情況。比如對節(jié)點使用.after/.before/.append等方法后,節(jié)點被添加到新的地方,原來的位置上的節(jié)點被移除了。有的時候需要保留原來位置上的節(jié)點,僅僅是需要一個副本添加到對應位置,這個時候克隆就有了使用場景。
jQuery.fn.clone克隆當前匹配元素集合的一個副本,并以jQuery對象的形式返回。
你還可以指定是否復制這些匹配元素(甚至它們的子元素)的附加數(shù)據(jù)( data()函數(shù) )和綁定事件。
jQueyr.fn.clone: function( withDataAndEvents, deepDataAndEvents )參數(shù)描述
withDataAndEvents | 可選/Boolean類型,是否同時復制元素的附加數(shù)據(jù)和綁定事件,默認為false。 |
deepWithDataAndEvents | 可選/Boolean類型,是否同時復制元素的所有子元素的附加數(shù)據(jù)和綁定事件,默認值即為參數(shù) |
第一步,先克隆出DOM節(jié)點。對支持正確的節(jié)點克隆(即支持elem.cloneNode并保證克隆無誤)的DOM節(jié)點直接使用cloneNode(true),否則自建一個節(jié)點來保存被克隆數(shù)據(jù)然后獲取該節(jié)點。
if ( jQuery.support.html5Clone || jQuery.isxmlDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { clone = elem.cloneNode( true );// IE<=8 不能正確克隆已分離、未知的節(jié)點//直接新建一個相同的節(jié)點,然后獲取} else {
//fragmentDiv是全局變量 fragmentDiv.innerHTML = elem.outerHTML; fragmentDiv.removeChild( clone = fragmentDiv.firstChild );}
第二步,如果是IE瀏覽器下,則需要通過fixCloneNodeIssues( node, destElements[i] );來逐個修正IE克隆問題。IE克隆解決方案全部包含在了fixCloneNodeIssues中,下一節(jié)詳細分析。里面的jQuery.support內(nèi)容點擊這里查看更多
//針對ie克隆問題修正if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { //在這里我們不使用Sizzle的原因是: http://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); //修正所有IE克隆問題 for ( i = 0; (node = srcElements[i]) != null; ++i ) { // Ensure that the destination node is not null; Fixes #9587 if ( destElements[i] ) { fixCloneNodeIssues( node, destElements[i] ); } }}
第三步,如果要克隆緩存數(shù)據(jù)(包括普通數(shù)據(jù)和綁定事件),克隆之。
//克隆綁定的事件if ( dataAndEvents ) { if ( deepDataAndEvents ) { srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); for ( i = 0; (node = srcElements[i]) != null; i++ ) { cloneCopyEvent( node, destElements[i] ); } } else { cloneCopyEvent( elem, clone ); }}
備注:cloneCopyEvent函數(shù)中會將原節(jié)點的數(shù)據(jù)保存到克隆節(jié)點中,然后將原節(jié)點的事件綁定到新的克隆節(jié)點上

function cloneCopyEvent( src, dest ) { if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { return; } var type, i, l, oldData = jQuery._data( src ), curData = jQuery._data( dest, oldData ),//dest是克隆對的節(jié)點 events = oldData.events; if ( events ) { //保證被克隆的節(jié)點的事件對象干凈,確保沒有后面添加的事件沒有重復 delete curData.handle; curData.events = {}; for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { jQuery.event.add( dest, type, events[ type ][ i ] ); } } } // 使克隆的數(shù)據(jù)對象化 if ( curData.data ) { curData.data = jQuery.extend( {}, curData.data ); } }
新聞熱點
疑難解答