前端小白之--snabbdom

https://zhuanlan.zhihu.com/p/69401061

image.png
import { h, init } from 'snabbdom'

// 1. hello world
// 参数:数组,模块
// 返回值:patch函数,作用对比两个vnode的差异更新到真实DOM
let patch = init([])
// 第一个参数:标签+选择器
// 第二个参数:如果是字符串的话就是标签中的内容
let vnode = h('div#container.cls', { 
  hook: {
    init (vnode) {
      console.log(vnode.elm)//undefined
    },
    create (emptyVnode, vnode) {
      console.log(vnode.elm)//<div id="container" class="cls">Hello World</div>
    }
  }
}, 'Hello World')

let app = document.querySelector('#app')
// 第一个参数:可以是DOM元素,内部会把DOM元素转换成VNode
// 第二个参数:VNode
// 返回值:VNde
let oldVnode = patch(app, vnode)

// 假设的时刻
vnode = h('div', 'Hello Snabbdom')

patch(oldVnode, vnode)
image.png
  • init函数
    功能:init(modules, domApi),返回 patch() 函数(高阶函数)
    为什么要使用高阶函数?
    因为 patch() 函数再外部会调用多次,每次调用依赖一些参数,比如:
    modules/domApi/cbs
    通过高阶函数让 init() 内部形成闭包,返回的 patch() 可以访问到 modules/domApi/cbs,而
    不需要重新创建
    init() 在返回 patch() 之前,首先收集了所有模块中的钩子函数存储到 cbs 对象中
    init内部最后return返回patch函数,把vnode渲染成真实的dom。并返回vnode,作为下次处理的旧节点
  • patch函数
    patch函数
  • createElm 把虚拟Vnode转化为真实的dom
    image.png
    image.png
  • patchVnode
    image.png
  • updateChildren
    ■ 功能:diff 算法的核心,对比新旧节点的 children,更新 DOM
    ■ 执行过程:
    1.要对比两棵树的差异,我们可以取第一棵树的每一个节点依次和第二课树的每一个节点比较,但是这样的时间复杂度为 O(n^3),
    2.在DOM 操作的时候我们很少很少会把一个父节点移动/更新到某一个子节点因此只需要找同级别的子节点依次比较,然后再找下一级别的节点比较,这样算法的时间复杂度为 O(n)。
    3.在进行同级别节点比较的时候,首先会对新老节点数组的开始和结尾节点设置标记索引,遍历的过程中移动索引
    4.在对开始和结束节点比较的时候,总共有四种情况
    ◇ oldStartVnode / newStartVnode (旧开始节点 / 新开始节点)
    ◇ oldEndVnode / newEndVnode (旧结束节点 / 新结束节点)
    ◇ oldStartVnode / oldEndVnode (旧开始节点 / 新结束节点)
    ◇ oldEndVnode / newStartVnode (旧结束节点 / 新开始节点)


    四种

    (oldStartVnode / newStartVnode ) || (oldEndVnode / newEndVnode)

    oldEndVnode / newEndVnode

    oldEndVnode / newStartVnode

    查找key

    循环结束
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容