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()

(完)


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

查看所有标签

猜你喜欢:

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

离散数学及其应用(原书第7版)

离散数学及其应用(原书第7版)

Kenneth H. Rosen / 徐六通、杨娟、吴斌 / 机械工业出版社 / 2015-1-1 / 129

《计算机科学丛书:离散数学及其应用(原书第7版)》是介绍离散数学理论和方法的经典教材,已经成为采用率最高的离散数学教材,被美国众多名校用作教材,获得了极大的成功。中文版也已被国内大学广泛采用为教材。作者参考使用教师和学生的反馈,并结合自身对教育的洞察,对第7版做了大量的改进,使其成为更有效的教学工具。《计算机科学丛书:离散数学及其应用(原书第7版)》可作为1至2个学期的离散数学课入门教材,适用于数......一起来看看 《离散数学及其应用(原书第7版)》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具