为什么在有vdom? 因为操作真实dom慢,浏览器运行js快,使用js模拟真实dom(vdom)。目的可以快速响应视图更新。
新旧vnode对比? 目的是找到最小的差异,只更新差异。
snabbdom源码: 1)看任何框架的源码,只看主干和要点,不要去扣细节。 2)源码是ts。ts的类型约束,不需要关注。
h函数:
1)作用:生成一个vnode。
2)源码位置:src/h.ts
3)输入和输出:function h(sel:string, data:VNodeData,children:VNodeChildren):VNode;
返回:return vnode(sel, data, children, text, undefined);
vnode函数: 1)作用:生成一个vnode(使用js去模拟真实dom) 2)源码位置:src/vnode.ts 3) 返回:return {sel, data, children, text, elm, key};
patch函数: 1)作用:将newVnode更新到oldVnode上,或将newVnode挂载到某个节点上。 第1次调用patch是初次渲染,后面再去调用patch就是新旧vnode对比。 2)源码位置:src/snabbdom.ts 当中有一个init函数,最后返回patch函数 3)输入和输出:function patch(oldVnode: VNode | Element, vnode: VNode): VNode 4)对于patch函数,需要考虑第一个参数是Vnode还是Element两种情况。
diff: 假如patch函数的第一个参数是vnode,就需要进行diff算法。新旧vnode都是树结构。 如果让你找差异: 1)先遍历tree1,两遍历tree2,找到差异,还需要排序。1000个节点,要计算出1亿次,算法复杂度O(n^3),算法不可用。 2)A) 只比较同一层级,不跨级比较。 B) 如果tag不相同,直接删除重建,不会再深度比较了。目的是为了快速找到差异。 C) tag和key,都相同,则认为是相同的节点,不再比较交,进行复用。
总结: diff算法中,细节不是关键,如头头,尾尾...。算法的过程都不是核心。 核心概念才是关键:h vnode patch key patchVnode(addVnodes,removeVnodes,updateChildren,key) 细节不重要,updateChildren的过程也重要,不要深究。
vdom有什么价值?
答:让我们更快实现数据驱动视图,尽可能少的操作真实DOM。
响应式的作用: 监听data的数据变化,仅此而已。
vdom: snabbdom 是一个vdom的库 h -> vnode vnode -> vnode结构 path -> 调用patchVnode patchVnode -> 调用addVnodes | 调用removeVnodes | updateChildren | key