snabbdom
使用流程
1、init: 使用模块初始化一个patch function;
const patch = init([styleModule, eventListenersModule]);
2、创建一个vnode;
let vnode = h('div#container.demo', [
h('h1', { style: { backgroundColor: 'cyan' } }, 'title'),
h('p', { on: { click: eventHandler } }, 'pppppp'),
h('!', 'sdsdsd')
])
3、选择一个容器,将vnode patch到容器中;
const container = document.getElementById("container");
patch(container, vnode);
4、生成一个新的vnode;
const newVnode = h(
"div#container.two.classes",
{ on: { click: anotherEventHandler } },
[
h(
"span",
{ style: { fontWeight: "normal", fontStyle: "italic" } },
"This is now italic type"
),
" and this is still just normal text",
h("a", { props: { href: "/bar" } }, "I'll take you places!"),
]
);
5、将旧vnode更新为新vnode;
patch(vnode, newVnode);
init模块
包含的关键函数:
- createElm:根据传入的vnode递归创建一颗真实DOM树;
- updateChildren:递归比较新传入的新旧节点以及子节点的差异(diff算法);
- patchVnode:比较新老节点的差异(比较是否有子节点以及文本内容,新旧节点都有子节点时调用updateChildren);
- patch:init模块导出的函数
patch函数
function patch(
oldVnode: VNode | Element | DocumentFragment,
vnode: VNode
): VNode
patchVnode
function patchVnode(
oldVnode: VNode,
vnode: VNode,
insertedVnodeQueue: VNodeQueue
)
updateChildren
function updateChildren(
parentElm: Node,
oldCh: VNode[],
newCh: VNode[],
insertedVnodeQueue: VNodeQueue
)

Diff算法的核心
四种更新策略,按比较的先后顺序排列,依次为:
(1)旧前与新前;
(2)旧后与新后;
(3)旧前与新后;
(4)旧后与新前;
(1)旧前与新前;
(2)旧后与新后
(3)旧前与新后
(4)旧后与新前