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

3次阅读

共计 2768 个字符,预计需要花费 7 分钟才能阅读完成。

前言:跟 当我调用了 $().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;
},
这个一看就懂,就不解释了

(完)

正文完
 0