6. 「snabbdom@3.5.1 源码分析」总结

67 阅读2分钟

这是一个系列文章,请关注snabbdom@3.5.1 源码分析专栏、vue@2.6.11 源码分析 专栏


module的作用

通过pacth过程中的各种钩子,和vnode.data提供的自定义数据(class/style/dataset等等)来拦截并做出相应处理。在diff过程中DOM的class/style/attributes等等都是交给模块处理,diff本身只关心的树结构,节点是否可以复用,如果不能复用就会通过createElm/setTextContent来创建新的元素

diff过程中的细节

vnode.children和vnode.text

vnode.children和vnode.text对立处理的,vnode.text优先级高于vnode.children(正常情况下vnode这两个属性不应该同时有值),如果有children则递归对比(-> updateChildren),如果有text则直接对比text是否相等并修改(不用递归)

patch、patchVnode、updateChildren的区别

  1. patch: 是不太确定新老vnode是否相等是给开发者调用的用来更新界面的;

  2. patchVnode是内部方法,该方法是用来对比两个相同(sameVnode)的新老vnode的的孩子节点差异的,该方法主要处理vnode.text和vnode.children的差异处理。 init.ts

如果存在 vnode.text,则直接在当前方法中处理掉,显然没必要进入递归处理;而vnode.children则需要递归对比,新老孩子节点的复用情况。

  1. updateChildren 第二点说了,其目的是对比孩子节点(数组,只对比一层),哪些老节点可以被复用(原地保留或者移动),哪些老节点需要删除,哪些新节点需要添加

image.png


dom节点先创创建再衔接: 移动的DOM或者新创建的DOM会调用document.insertBefore/appendChill等api来衔接到DOM树中。

生命周期

Snabbdom 提供了一系列丰富的生命周期函数,这些生命周期函数适用于拓展 Snabbdom 模块或者在虚拟节点生命周期中执行任意代码。

名称触发节点回调参数
prepatch 开始执行none
initvnode 被添加vnode
create一个基于 vnode 的 DOM 元素被创建emptyVnode, vnode
insert元素 被插入到 DOMvnode
prepatch元素 即将 patcholdVnode, vnode
update元素 已更新oldVnode, vnode
postpatch元素 已被 patcholdVnode, vnode
destroy元素 被直接或间接得移除vnode
remove元素 已从 DOM 中移除vnode, removeCallback
post已完成 patch 过程none

适用于模块(module.xxx):pre, create,update, destroy, remove, post

适用于单个元素(vnode.data.hook.xxx):init, create, insert, prepatch, update,postpatch, destroy, remove

虽然很多钩子的触发时机是一致,但是为什么还要区分这两类钩子呢?因为有些逻辑是共同的,这些逻辑收敛到模块中,而有些逻辑对于不同的vnode有差异,因此交给具体的vnode自己处理。