「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
removeVnode 和 addvnodes
本章我们继续进行Snabbdom 源码解析篇章,我们的目标是 removeVnodes 和 addvnodes 函数
这两个函数是在 patch 函数中内部调用的
- removeVnodes:从DOM树上批量移除VNodes对应的DOM元素
- addvnodes:从DOM树上批量添加VNodes对应的DOM元素
removeVnodes 函数解析
理解一个函数就要先从他的参数开始理解
参数解析
- parentElm:要删除的元素所在的父元素
- vnodes: 这个参数是一个数组,存储的时候要删除的DOM元素对应的VNode
- startIdx: 数组中要删除的节点的起始位置
- endIdx: 数组中要删除的节点的结束位置
代码解析
for (; startIdx <= endIdx; ++startIdx) {
let listeners: number
let rm: () => void
const ch = vnodes[startIdx]
startIdx <= endIdx; ++startIdx这里是根据用户传入的参数,对要截取的点const ch = vnodes[startIdx]找到要删除的元素节点
接着
if (ch != null) {
...
}
这一步的判断就很简单了,是否有要被删除的元素节点
如果有要被删除的元素节点,那么紧接着
if (isDef(ch.sel)) {
....
} else { // Text node
api.removeChild(parentElm, ch.elm!)
}
根据元素的sel属性判断是否元素节点or文本节点
- 如果
ch.sel !== undefined元素节点 - 如果
ch.sel === undefined文本节点
如果被删除的节点是元素节点的话
...
invokeDestroyHook(ch)
listeners = cbs.remove.length + 1
rm = createRmCb(ch.elm!, listeners)
for (let i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm)
const removeHook = ch?.data?.hook?.remove
if (isDef(removeHook)) {
removeHook(ch, rm)
} else {
rm()
}
- invokeDestroyHook: 触发了 destroy 的钩子函数
listeners = cbs.remove.length + 1获取cbs.remove的钩子函数 并 +1,这个变量的作用是防止变量重复删除DOM元素rm = createRmCb(ch.elm!, listeners):createRmCb是个高阶函数,他是一个返回真正删除DOM元素的函数ch.elm: 要被删除的元素listeners: 防止变量重复删除DOM元素
for (let i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm): 遍历remove方法,然后传入ch和rm(也就是createRmCb返回的函数)const removeHook = ch?.data?.hook?.remove:这步主要是获取用户传入的钩子函数,如果有传入remove钩子函数返回该函数,没有返回undefined- 最后这个
if节点就是判断removeHook是否存在,然后执行对应的方法
如果被删除的节点是文本节点的话
我们会直接调用 api.removeChild(parentElm, ch.elm!) 删除父元素中的elm属性
到这里我们的 removeVnodes就完结了
addVnodes 函数
function addVnodes (
parentElm: Node,
before: Node | null,
vnodes: VNode[],
startIdx: number,
endIdx: number,
insertedVnodeQueue: VNodeQueue
) {
for (; startIdx <= endIdx; ++startIdx) {
const ch = vnodes[startIdx]
if (ch != null) {
api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before)
}
}
}
参数:
- parentElm: 父元素
- before: 参考节点
- vnodes:添加的节点
- startIdx、endIdx: 开始结束节点
- insertedVnodeQueue: 存储刚刚插入的具有
inserted钩子函数的节点
接下来的代码就很简单了
通过createElm(ch, insertedVnodeQueue)创建DOM元素,插入到DOM树种,完结
算了 我这种傻*文章也不要赞了。。。 我自己都觉得很傻,在总结什么也不知道