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

栏目: jQuery · 发布时间: 5年前

内容简介:前言:unwrap() 的解析请看

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

前言:

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() 方法,并且只传了两个参数 thisselector

第三个参数是 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") ,就是返回所有 <p> 标签中,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() 我们下一篇讲。。(有点累)

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

(完)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Database Design and Implementation

Database Design and Implementation

Edward Sciore / Wiley / 2008-10-24 / 1261.00 元

* Covering the traditional database system concepts from a systems perspective, this book addresses the functionality that database systems provide as well as what algorithms and design decisions will......一起来看看 《Database Design and Implementation》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试