本節說一下DOM操做模塊裏的包裹元素子模塊,該模塊可將當前匹配的元素替換指定的DOM元素,有以下方法:html
舉個栗子:node
writer by:大沙漠 QQ:22969969jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> </head> <body> <p>你好</p> <p>Hello World</p> <div> <i> <span>測試文本</span> </i> </div> <button id="b1">按鈕1</button> <br/> <button id="b2">按鈕2</button><button id="b3">按鈕3</button> <br/> <button id="b4">按鈕4</button><br/><button id="b5">按鈕5</button> <script> b1.onclick=function(){$('p').wrap('<div></div>')} //內部將<div></div>轉化爲jQuery對象放到第一個匹配元素<p>你好</p>以前,再將匹配元素移動到該DOM節點內部 b2.onclick=function(){$('p').wrapAll('<div></div>')} //內部將<div></div>轉化爲jQuery對象放到第一個匹配元素<p>你好</p>以前,再將匹配元素移動到該DOM節點內部 b3.onclick=function(){$('p').wrapAll('<div><p></p></div>')} //若是含有子節點,則會將匹配元素移動到子節點裏面 b4.onclick=function(){$('p').wrapInner('<div></div>')} //在每一個匹配元素的內容先後添加一層DOM節點(包裹層) b5.onclick=function(){$('span').unwrap() } //移除每一個匹配元素的父元素,並讓匹配元素佔有該節點位置 </script> </body> </html>
渲染以下:app
對應的DOM樹以下:函數
點擊按鈕1會在全部的P標籤上加一個div父節點,以下:源碼分析
點擊按鈕2將在第一個p標籤前添加一個div,而後把全部p標籤放到div之下,以下:測試
點擊按鈕3將在第一個p標籤前添加一個div>p雙層DOM,而後把全部p標籤放到div之下,以下:this
點擊按鈕4將在p標籤內最外層嵌套一層div標籤,以下:spa
點擊按鈕5將會去除 span的上一層DOM節點,以下:code
若是再次點擊,會將span的上一層DOM繼續移除,直到遇到body節點爲止
源碼分析
wrapInner和wrap都是基於wrapAll實現的,wrapAll實現以下:
jQuery.fn.extend({ wrapAll: function( html ) { //在匹配的元素外面放置html元素。html參數能夠是html片斷、選擇器表達式、jQuery對象、DOM元素或函數。 if ( jQuery.isFunction( html ) ) { //若是html是函數 return this.each(function(i) { jQuery(this).wrapAll( html.call(this, i) ); //遍歷匹配元素,在每一個匹配元素上執行html函數,並用該函數的返回值做爲參數迭代調用.wrapAll()函數。 }); } if ( this[0] ) { //若是當前有匹配元素 // The elements to wrap the target around var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); //將html轉化爲一個jQuery對象 if ( this[0].parentNode ) { //若是當前第一個匹配元素有父元素, wrap.insertBefore( this[0] ); //則把建立的包裹元素插入第一個匹配元素以前。 } wrap.map(function() { //遍歷wrap元素 var elem = this; //elem是建立的包裹元素的引用 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { //若是html裏含有一個子節點 elem = elem.firstChild; //則重置elem爲html的子節點,上面的按鈕3會執行到這裏 } return elem; }).append( this ); //這一行的this是當前匹配的jQuery對象,把每一個匹配元素移動到插入的元素以後 } return this; }, })
wrapAll首先會把參數轉化爲一個jQuery對象,而後插入到當前第一個匹配元素的前面,最後以生成的jQuery對象爲主句,調用append()將當前匹配匹配的全部元素添加到新生成的jQuery對象對應的DOM節點內部。對應上面的按鈕2
wrap()實現以下:
jQuery.fn.extend({ wrap: function( html ) { //在每一個匹配元素的外層添加一層DOM元素 var isFunction = jQuery.isFunction( html ); //在每一個匹配元素先後包裹一段HTML結構,該方法會遍歷匹配元素集合,在每一個元素上調用.wrapAll()方法。 return this.each(function(i) { jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); //依次調用wrapALl()函數 }); }, })
wrapInner的實現以下:
jQuery.fn.extend({ wrapInner: function( html ) { //用於在匹配元素集合中每一個元素的內容先後包裹一段HTML結構,該方法會遍歷匹配元素集合 if ( jQuery.isFunction( html ) ) { //若是html是函數 return this.each(function(i) { jQuery(this).wrapInner( html.call(this, i) ); //遍歷匹配元素,在每一個匹配元素上執行html函數,並用該函數的返回值做爲參數迭代調用.wrapInner()函數。 }); } return this.each(function() { //遍歷匹配元素集合 var self = jQuery( this ), contents = self.contents(); //先獲取全部子節點 if ( contents.length ) { //若是有子節點 contents.wrapAll( html ); //調用wrapAll(html)爲當前元素的全部內容包裹一段HTML代碼。 } else { self.append( html ); //若是當前元素沒有內容,則直接將參數html插入當前內容。 } }); }, })
unwrap的實現以下:
Query.fn.extend({ unwrap: function() { //移除匹配元素集合中每一個元素的父標籤,並把匹配元素留在父元素的位置上 return this.parent().each(function() { //先遍歷父節點 if ( !jQuery.nodeName( this, "body" ) ) { //若是不是body元素 jQuery( this ).replaceWith( this.childNodes ); //則調用replaceWith將this.childNodes替換爲this,注意,這裏的this上下文是父節點 } }).end(); } })