天天看点

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在后面!