无所事事的样子开始了摸鱼的一天
Virtual DOM (虚拟DOM) 的实现原理
用js对象来描述真实DOM元素,真实DOM的属性极其之多,所以操作虚拟DOM的成本比真实DOM成本低
为了简化DOM操作,使用MVVM框架解决了视图和状态同步的问题
为了简化视图操作使用了模板引擎,但是没有解决跟踪状态变化的问题,数据发生变化的时候无法获取上一次的状态,只能删除原有的元素,替换上改变后的元素
虚拟DOM的好处是当状态改变时不需要立即更新DOM元素,而是用diff算法进行对比前后差异进行更新DOM元素
- 维护视图和状态的关系
- 复杂视图情况提升渲染性能 (不复杂的Hello World的你用这玩意干啥)
- 除了渲染DOM,还能实现SSR、原生应用、小程序这些东西(虚拟的东西只需要你有转换方式就可以转换了啊,毕竟它只是一个js的对象而已,单纯的只是一个孩子啊)
diff算法简述
按照如下顺序去比较节点
- oldStartVnode / newStartVnode (旧开始节点 / 新开始节点)
- oldEndVnode / newEndVnode (旧结束节点 / 新结束节点)
- oldStartVnode / oldEndVnode (旧开始节点 / 新结束节点)
- oldEndVnode / newStartVnode (旧结束节点 / 新开始节点)
- 如果不是以上四种情况
- 遍历新节点,使用 newStartNode 的 key 在老节点数组中找相同节点
- 如果没有找到,说明 newStartNode 是新节点
- 创建新节点对应的 DOM 元素,插入到 DOM 树中
- 如果找到了
- 判断新节点和找到的老节点的 sel 选择器是否相同
- 如果不相同,说明节点被修改了
- 重新创建对应的 DOM 元素,插入到 DOM 树中
- 如果相同,把 elmToMove 对应的 DOM 元素,移动到左边
透过Snabbdom分析
h函数
h函数用来创建VNode
- 函数重载
-
- 参数个数或类型不同的函数
-
- js中没有重载概念,ts中的重载是通过代码调整参数
// 重载示例
function add(a,b){return a+b}
function add(a,b,c){return a+b+c}
add(1,2)
add(1,2,3)
VNode
export interface VNode {
// 选择器
sel: string | undefined
// 节点数据 属性/样式/事件等
data: VNodeData | undefined
// 子节点 与 text互斥
children: Array<VNode | string> | undefined
// 真实dom
elm: Node | undefined
// 节点中内容 和children互斥
text: string | undefined
// 优化用 diff 算法上会使用它进行优化
key: Key | undefined
}
VNode渲染真实DOM
patch函数 会传入两个参数,新旧两个VNode
对比两个节点,然后对其进行操作(可以看做是打补丁,那里缺了补那里,那里丑了美化那里)
优化后的diff的过程只进行同层比较
—————————————————————————————————————————————————————— 我这废柴