jQuery源码解析之detach()/empty()/remove()/unwrap() 您所在的位置:网站首页 jquery源码解析之siblings方法 jQuery源码解析之detach()/empty()/remove()/unwrap()

jQuery源码解析之detach()/empty()/remove()/unwrap()

2023-09-05 02:46| 来源: 网络整理| 查看: 265

前言: unwrap() 的解析请看 jQuery源码解析之replaceWith()/unwrap() empty() 的解析请看 jQuery之text()的实现

一、$().empty()

作用:

清除被选元素的所有子节点和内容,包括事件和数据

注意:该方法不会移除被选元素本身或它的属性。

源码:

//源码6231行 empty: function() { var elem, i = 0; for ( ; ( elem = this[ i ] ) != null; i++ ) { //如果是元素节点的话 if ( elem.nodeType === 1 ) { // Prevent memory leaks //清空内容和事件,防止内存泄漏 jQuery.cleanData( getAll( elem, false ) ); // Remove any remaining nodes //清空节点所有内容 elem.textContent = ""; } } return this; }, 复制代码

简单实现:

$("#divTwo").empty() //相当于 function customEmpty() { let elem, i = 0,array=[] //DOM节点集合,querySelectorAll //注意for循环的写法 for (; (elem = this[i]) != null; i++) { //如果是元素节点的话,清空该节点的所有内容 if (elem.nodeType === 1) { //jQuery.cleanData( getAll( elem, false ) ); elem.textContent = ""; } } //单个DOM节点,querySelector if(this[i]===undefined){ if (this.nodeType === 1) { //jQuery.cleanData( getAll( elem, false ) ); this.textContent = ""; } } return this; } customEmpty.call(divTwo) 复制代码

二、$().remove()

作用:

移除被选元素自身,包括所有的数据、事件和子节点。

源码:

//移除被选元素,包括所有的文本和子节点,不会保留移除元素的副本 //源码6159行 remove: function( selector ) { return remove( this, selector ); }, 复制代码

解析:

可以看到,$().remove() 方法实际上调用的是外部的大的 remove() 方法,并且只传了两个参数this、selector

第三个参数是 keepData,即是否保留被移除元素的事件和数据,没有传参即默认false,在下面的 detach() 方法也是调用的 remove() 方法,并且第三个参数传了 true

detach: function( selector ) { return remove( this, selector, true ); }, 复制代码

1、remove():

//源码6037行 //$().remove()调用:selector, undefined, undefined function remove( elem, selector, keepData ) { console.log(elem,selector,'elem6041') var node, //remove()不带参数的话,nodes=目标元素 //$("p").remove("#pTwo") elem=$("p") selector=#pTwo nodes = selector ? jQuery.filter( selector, elem ) : elem, i = 0; console.log(nodes,'nodes6061') for ( ; ( node = nodes[ i ] ) != null; i++ ) { //如果keepData不为true,并且node为元素节点,则清除数据和事件 if ( !keepData && node.nodeType === 1 ) { jQuery.cleanData( getAll( node ) ); } //如果父节点存在,则removeChild if ( node.parentNode ) { if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { setGlobalEval( getAll( node, "script" ) ); } node.parentNode.removeChild( node ); } } return elem; } 复制代码

解析:

① nodes 是经过处理后得到的要被移除的节点集合 ② 循环 nodes,依次去除 nodes[i] 的事件和数据 ③ 找到 nodes[i] 的父节点,并调用原生JS的 removeChild() 方法,去掉 nodes[i]

简单实现:

//无参数====== $("#divTwo").remove() //相当于 // jQuery.cleanData(getAll(divTwo)) divTwo.parentNode.removeChild(divTwo) 复制代码

当 $().remove() 有参数的话(比如:$("p").remove("#pTwo")),就会调用jQuery.filter( selector, elem )方法

2、$.filter():

作用:

返回符合一定条件的元素,比如$("p").remove("#pTwo"),就是返回所有

标签中,id='pTwo' 的元素节点的集合,filter() 里面最后还调用了jQuery.find.matchesSelector()和jQuery.find.matches() 方法,这两个方法内都会调用 **Sizzle()**方法,而Sizzle()内调用了 select() 方法,select() 比较复杂,本文暂不贴码解析。

源码:

//返回符合一定条件的元素 //$("p").remove("#pTwo") expr=#pTwo elems=$("p") //源码2925行 jQuery.filter = function( expr, elems, not ) { //jQuery对象转换成DOM对象 var elem = elems[ 0 ]; if ( not ) { expr = ":not(" + expr + ")"; } //目标元素节点只有一个的情况 if ( elems.length === 1 && elem.nodeType === 1 ) { return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; } //elems 标签p的集合 //jQuery.grep,返回符合callback函数条件的数组, // 这里就是过滤掉非元素节点 return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; } ) ); }; 复制代码

3、$.grep()

作用:

返回符合 callback 函数条件的数组

源码:

//返回符合callback函数条件的数组 //elems 标签p的集合 //callback elems.nodeType===1 //invert 指定是否反转过滤结果,默认是false grep: function( elems, callback, invert ) { var callbackInverse, matches = [], i = 0, length = elems.length, //2 callbackExpect = !invert; //true // Go through the array, only saving the items // that pass the validator function //只保存符合callback函数的条件的elem(elem.nodeType===1) for ( ; i < length; i++ ) { //false callbackInverse = !callback( elems[ i ], i ); //false true if ( callbackInverse !== callbackExpect ) { matches.push( elems[ i ] ); } } return matches; }, 复制代码

4、有参数的$().remove()的简单实现:

//有参数====== $("p").remove("#pTwo") //相当于 // jQuery.cleanData(getAll(divTwo)) pTwo.parentNode.removeChild( pTwo ) 复制代码

三、$(). detach()

作用:

移除被选元素自身,但保留所有的数据、事件和子节点

注意:该方法在 不久会将删除的元素插入DOM的情况下,很有用

源码:

//移除被选元素,包括所有的文本和子节点,但会保留移除元素的副本,允许它们在以后被重新插入。 //注意那个 keepData:true detach: function( selector ) { return remove( this, selector, true ); }, 复制代码

可以看到,与 $().remove() 的区别就是该方法第三个参数传了 true 给大 remove() 方法,即 keepData

function remove( elem, selector, keepData ) { var node, //remove()不带参数的话,nodes=目标元素 //$("p").remove("#pTwo") elem=$("p") selector=#pTwo nodes = selector ? jQuery.filter( selector, elem ) : elem, i = 0; for ( ; ( node = nodes[ i ] ) != null; i++ ) { //如果keepData不为true,并且node为元素节点,则清除数据和事件 if ( !keepData && node.nodeType === 1 ) { jQuery.cleanData( getAll( node ) ); } //如果父节点存在,则removeChild if ( node.parentNode ) { //$.contains:判断指定元素内是否包含另一个元素。即判断另一个DOM元素是否是指定DOM元素的后代 if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { //把所有的script标签标记为已经执行 setGlobalEval( getAll( node, "script" ) ) } node.parentNode.removeChild( node ); } } return elem; } 复制代码

可以看到,在 keepData=true的时候,会不执行 jQuery.cleanData( getAll( node ) )方法,并且会执行 setGlobalEval( getAll( node, "script" ) )

使用:

//无参数====== // 该方法在 不久会将删除的元素插入DOM的情况下,很有用 let removeNodeOne=$("#divTwo").detach() //有参数====== let removeNodeTwo=$("p").detach("#pTwo") 复制代码

四、关于 getAll()、jQuery.cleanData() 我们下一篇讲。。(有点累)

(完)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有