我这废柴怎么可能逆袭的一生、第十天

224 阅读3分钟

无所事事的样子开始了摸鱼的一天

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的过程只进行同层比较

—————————————————————————————————————————————————————— 我这废柴

系列