jQuery源码解析之replaceWith()/unwrap()

jQuery源码解析之replaceWith()/unwrap()

前言:当我调用了$().append()后,jQuery内部发生了什么? 一样,replaceWith() 会经过 domManip()buildFragment() 的洗礼,最后调用原生JS的方法来实现。

所以,本文只讲述 jQuery 中最后对 replaceWith() 处理的相关代码。

想了解domManip()buildFragment()的,请看 当我调用了$().append()后,jQuery内部发生了什么?

一、示例代码

<body>
<script src="jQuery.js"></script>
<div id="divTwo">
  <p id="pTwo">这是divTwo</p>
</div>
<div id="divOne">
  <p>这是divOne</p>
</div>

<script>
  let divOne = document.querySelector("#divOne")
  let divTwo = document.querySelector("#divTwo")
  let pTwo = document.querySelector("#pTwo")
  
  // ===========replaceWith==============
  //注意:removedNode指向已经被移除的divTwo
  let removedNode=$("#divTwo").replaceWith("<span>永远</span>")
  console.log(removedNode,'removedNode21')
  //======相当于=====
  let spanA=document.createElement("span")
  spanA.innerText="永远"
  divTwo.parentNode.replaceChild(spanA,divTwo)
  
  // ==============unwrap================
  $("#pTwo").unwrap()
  //======相当于=====
  let pTwoFather=pTwo.parentNode
  if(pTwoFather.nodeName.toLowerCase()!=='body'){
    pTwoFather.parentNode.replaceChild(pTwo,pTwoFather)
  }
  
</script>
</body>

二、$().replaceWith()

作用:

把被选元素替换为新的内容

注意:$().replaceWith() 指向已经被移除的元素。

源码:

// 源码6324行
    // 把被选元素替换为新的内容
    replaceWith: function() {
      var ignored = [];
      // Make the changes, replacing each non-ignored context element with the new content
      return domManip( this, arguments, function( elem ) {
        //获取选择器的父节点
        var parent = this.parentNode;
        //$.inArray() 函数用于在数组中查找指定值,并返回它的索引值(如果没有找到,则返回-1)
        //inArray() 可以看成是indexOf()
        //如果ignored数组中没有目标元素的话
        if ( jQuery.inArray( this, ignored ) < 0 ) {
          //清除目标元素的事件
          jQuery.cleanData( getAll( this ) );
          if ( parent ) {
            //原生JS方法replaceChild(newnode,oldnode) 将某子节点替换成另一个
            parent.replaceChild( elem, this );
          }
        }
        // Force callback invocation
      }, ignored );
    }

解析:

① 先找到目标元素的父节点 this.parentNode

② 使用 $.cleanData() 清除目标元素上的 事件和缓存jQuery.cleanData( getAll( this ) )

③ 当父节点存在时,父节点调动replaceChild(),将待替换的元素 替换到 目标元素上

简单实现:

//注意:removedNode指向已经被移除的divTwo
  let removedNode=$("#divTwo").replaceWith("<span>永远</span>")
  console.log(removedNode,'removedNode21')
  //======相当于=====
  let spanA=document.createElement("span")
  spanA.innerText="永远"
  divTwo.parentNode.replaceChild(spanA,divTwo)

三、$().inArray()

作用:

查看元素在数组中的位置

源码:

//源码453行,查看元素在数组中的位置
    inArray: function( elem, arr, i ) {
      //indexOf:array.indexOf
      return arr == null ? -1 : indexOf.call( arr, elem, i );
    },

四:$().unwrap()

作用:

移除被选元素的父元素(父节点是body则无效

源码:

//源码9798行
    //移除被选元素的父元素(父节点是body则无效)
    unwrap: function( selector ) {
      //选中目标元素的父节点(除了body)
      this.parent( selector ).not( "body" ).each( function() {
        //this表示父节点
        //即父节点被它的子节点替换
        jQuery( this ).replaceWith( this.childNodes );
      } );
      return this;
    }

解析:

是在目标元素的爷爷节点上调用 replaceWith() 方法,将父节点替换成目标节点。

注意:目标元素的父节点是body的话,$().unwrap()方法无效。

简单实现:

$("#pTwo").unwrap()
  //======相当于=====
  let pTwoFather=pTwo.parentNode
  if(pTwoFather.nodeName.toLowerCase()!=='body'){
    pTwoFather.parentNode.replaceChild(pTwo,pTwoFather)
  }

五、$().parent()

作用:

返回被选元素的直接父元素

源码:

//源码3245行
    //11表示文档碎片
    //返回被选元素的直接父元素
    parent: function( elem ) {
      var parent = elem.parentNode;
      return parent && parent.nodeType !== 11 ? parent : null;
    },

这个一看就懂,就不解释了


jQuery源码解析之replaceWith()/unwrap()

(完)

相关推荐