本節說一下DOM操作模塊里的包裹元素子模塊,該模塊可將當前匹配的元素替換指定的DOM元素,有如下方法:
- wrap(html) ;在每個匹配元素的外層添加一層DOM元素 ;該方法會遍歷匹配元素集合,在每個元素上呼叫.wrapAll()方法 ;不同于wrapAll()的是該方法會在每個匹配元素外面都套一層html元素,
- wrapAll(html) ;會將html轉化為一個DOM節點并放在第一個匹配元素的前面,再把其他匹配元素也依次放進去 ;html可以是html片段、選擇器運算式、jQuery物件、DOM元素或函式,下同,
- wrapInner(html) ;在每個匹配元素的內容前后包裹HTML元素 ;該方法會遍歷匹配元素集合,并通過呼叫方法.wrapAll()為每個匹配元素的所有內容包裹一段HTML結構,
- unwrap() ;移除匹配元素集合中每個元素的父標簽,并把匹配元素留在父元素的位置上
舉個栗子:
writer by:大沙漠 QQ:22969969
<!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>
渲染如下:

對應的DOM樹如下:

點擊按鈕1會在所有的P標簽上加一個div父節點,如下:

點擊按鈕2將在第一個p標簽前添加一個div,然后把所有p標簽放到div之下,如下:

點擊按鈕3將在第一個p標簽前添加一個div>p雙層DOM,然后把所有p標簽放到div之下,如下:

點擊按鈕4將在p標簽內最外層嵌套一層div標簽,如下:

點擊按鈕5將會去除 span的上一層DOM節點,如下:

如果再次點擊,會將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(); } })
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/31434.html
標籤:jQuery
