从 snabbdom 看虚拟dom

Vue 的虚拟 DOM 方案衍生于snabbdom 工具,所以我们来看下snabbdom都做了什么

snabbdom只有200行的代码量,非常适合阅读。

snabbdom

核心关注点

关于虚拟DOM的实现以下几个核心内容是我们必须关注的:

  1. compile 将真实DOM编译为Vnode
  2. diff 对比新旧Vnode,知道两个Vnode间的变化
  3. patch 将上一步中对比得到的变化以补丁的方式更新到真实DOM中

源码阅读

snabbdom的源码采用tyscript编写

文件结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
src
├── helpers
│ └── attachto.ts # 定义了AttachData,VNodeDataWithAttach ,VNodeWithAttachData 等数据结构
├── modules # 该文件夹中主要存放一些在更新dom差异的时候需要的操作
│ ├── attributes.ts # 在vnode更新的时候,更新dom中的attrs操作。
│ ├── class.ts # 在vnode更新的时候,更新dom中的class操作。
│ ├── dataset.ts # 在vnode更新的时候,更新dom中的dataset(自定义数据集)操作。
│ ├── eventlisteners.ts # 在vnode更新的时候,更新dom中的eventlisteners(自定义数据集)操作。
│ ├── hero.ts # 在vnode更新的时候,和动画效果有关的支持
│ ├── module.ts # 定义的module结构
│ ├── props.ts # 在vnode更新的时候,更新dom中的props操作。
│ └── style.js # 在vnode更新的时候,更新dom中的style操作。
├── h.ts # 帮助函数主要用来操作生成vnode的。
├── hooks.ts # 定义snabbdom在运行的过程中hooks的模型。
├── htmldomapi.ts # 对浏览器的dom的api进行二次包装,可以直接操作,html的dom的api。
├── is.ts # is函数主要是针对做一些数据类型判断,分 primitive和array类型。
├── snabbdom.bundle.ts # snabbdom.ts、attributes、class、props、style 、eventListenersModule和h组成了这个ts文件。
├── snabbdom.ts # 主要文件,程序的主线逻辑都在这个文件里。
├── thunk.ts # thunk这个文件不知道干什么的,但是不影响理解主线逻辑。
├── tovnode.ts # 提供了toVNode的方法,把真实dom转化为vnode。
└── vnode.ts # 定义了vnode的模型和转化成为vnode的工具方法。

从上述文件结果可看出snabbdom.ts 是整个代码的主线, 那么我们从这里入手开始看源码