天天看點

jQuery源碼分析之remove和detach方法的差別

請提前閱讀:點選打開連結

detach源碼分析:

detach: function( selector ) {
		return this.remove( selector, true );
	}
           

可見detach内部調用的是remove函數,同時把selector傳入remove方法,但是第二個參數是true,是以remove方法中的keepData是true表示不會調用裡面的cleanData函數,這樣,remove和detach的差別就顯而易見了。

總結:

remove方法會移除該元素以及該元素的子元素下面的所有的資料和事件,但是detach方法不會移除該元素以及該元素的子元素的下面的所有的事件和資料!

之是以能夠這樣包括自身和子元素是因為:在remove源碼中調用了getAll(elem)是以在getAll傳回值裡面會包含調用元素,是以detach,remove都會傳回子元素以及調用者元素!

在這裡給出一個重要的例子:(怎麼把移除的節點找回來)

<div id="me1">
	I can not removed
</div>
<div class="removed" id="me2">
	I can  removed
</div>
           

JS部分:

var removed=$("div");
var removedMark=removed.remove(".removed");
//console.log(removed.length);//列印2
//removedMark傳回值是$("div"),是以把他添加到body上面的時候會建立文檔片段,該文檔碎片會包含$("div")
//中所有的元素,是以最後不管你調用append還是prepend結果都是一樣的!注意:這裡注意背景調用的是buildFragment
//不是克隆,是以雖然id為m1沒有被移除,但是在建立文檔碎片以後他的位置已經發生移動了,因為DOM數不可能有
//兩個完全一樣的節點,因為他們的指針是相同的!
removedMark.prependTo($("body"));
           

測試用例2:(交換兩個DOM節點的位置)

var frag=jQuery.buildFragment([$("#me2")[0],$("#me1")[0]],document,false,this);//如果沒有後面那一句append,這時候兩個div都已經消失了!
  $(frag).appendTo($("body"));
           

注意:這個測試用例你會發現body中的兩個div的位置已經發生交換了!

note:要知道append背景調用了buildFragment,而且該方法沒有對節點進行克隆,是以如果建立fragment時候該節點已經在DOM樹上,那麼也會把節點移動到該fragment上,因為DOM樹中fragment中的DOM和文檔中的DOM指針相同。是以上面調用append和prepend方法是一樣的,因為文檔碎片中始終m1在前面,m2在後面!