美文网首页
diff算法

diff算法

作者: 看到这朵小fa了么 | 来源:发表于2020-05-20 15:28 被阅读0次

    vue引入vdom的优势

    vue在已经知道哪里更新的前提下还是引入的VDOM,这是因为除了对更新的优化之外,VDOM还有其他的优势
    1、VDOM将dom结构抽象出来,上层的组件同样可以抽象化具有更高的适配能力
    2、VDOM的结构一致,可以跨平台渲染 如weex
    3、配合diff算法进行比对更新,在最小颗粒度和对比范围找到平衡点

    diff算法

    https://blog.csdn.net/chenzhizhuo/article/details/101531228

    平层对比减少时间复杂度n3到n,比对过程是OldVnode和vnode进行对比,以vnode的视图为结果

    patchVnode()
    • 如果两个节点是静态节点直接跳过对比(在编译时会进行标记)
    • 如果两个节点的根节点不同 则直接进行替换,创建vnode节点插入dom,移除OldVnode的节点即可
    • 两个节点相同且具有比较的价值 则进行patchVnode(OldVnode, vnode)的过程,否则执行上一步
    • vode节点不是文本节点则比较:
      1、两个节点都有子节点 且子节点不同则进行updateChild()
      2、只有vnode有子节点,则进行节点创建和插入
      3、只有oldNode有子节点,则进行子节点的移除,如果是文本节点则清空
    • vnode是文本节点则将OldVnode节点置文本节点
    • 如果vnode先结束则将OldVnode中多余的节点移除
    • 如果OldVnode先结束则将vnode中多余的节点进行创建和插入
    // 判断两个节点是否值得进行比对的方法是sameVnode()
    function sameVnode (a, b) {
      return (
        a.key === b.key &&  // key值
        a.tag === b.tag &&  // 标签名
        a.isComment === b.isComment &&  // 是否为注释节点
        // 是否都定义了data,data包含一些具体信息,例如onclick , style
        isDef(a.data) === isDef(b.data) &&  
        sameInputType(a, b) // 当标签是<input>的时候,type必须相同
      )
    }
    
    updateChild()

    其中难点在于updateChild的过程:

    • 首先对于新旧节点和Dom视图进行标记,开始和结束索引,注意遇到undefined跳过即可
    • 第一步进行快捷对比
      1、OldStart和vStart匹配成功则都向后移动一位
      2、OldStart和vEnd匹配成功则将Dom视图的OldStart移动到最后,最后将vEnd向前移动一位,OldStart后移一位
      3、OldEnd和vEnd匹配成功则都向前移动一位
      4、OldEnd和vStart匹配成功则将Dom视图的OldEnd移动到最前,最后将vStart后移一位,OldEnd向前移动一位
    • 快捷匹配失败则进行key值匹配
      1、vStart进行key值匹配成功则将Dom视图中对应的OldIndex节点移动到vStart的位置,将OldIndex的值置为undefined,vStart后移一位
      2、匹配失败则说明该节点是新的,创建并进行插入到Dom视图中对应的OldStart前即可
    例题分析
    • 将数组的第一个元素插入到最后[1,2,3,4]=> [2,3,4,1]
      1、快捷对比元素1匹配成功,则Dom更新[1,2,3,4]=>[2,3,4,1]
      2、OldStart后移 vStart前移一位,后都快捷对比成功
    • [A,B,C,D]=>[E,C,A,D,B]
      1、E快捷对比失效则进行Key值查找,查找失败则直接创建Dom更新为[E,A,B,C,D],vStart后移一位
      2、C进行快捷查找失败,进行Key查找成功,Dom更新为[E,C,A,B,D],OldVnode中C置为undefined,vStart后移一位
      3、A头匹配成功,开始节点均后移一位
      4、B快捷查找成功,Dom更新为[E,C,A,D,B],vEnd前移一位,OldStart后移一位
      5、OldStart遇到undefined跳过自动后移一位
      6、D快捷匹配成功 后移一位,跳出循环结束

    功能函数

    emptyNodeAt 将一个真实的无子节点的dom节点转化为vnode形式

    如:<div id='a' class='b c'></div>

    将转换为{sel:'div#a.b.c',data:{},children:[],text:undefined,elm:<div id='a' class='b c'>}

    sameVnode 比较两个vnode节点是否相似 相似patch 不同直接进行移除和添加

    createElm 通过vnode来创建真实的dom节点,并将其赋值给vnode.elm 。递归将vnode节点构建成dom树 触发全局的create钩子 推进insertedVnodeQunue ,实现批量插入触发insert回调

    removeVnodes 批量删除dom节点 配合invokeSestoryHook触发destory回调和createRmCb 对remove回调进行计数

    addVnodes 将vnode转化后的dom节点插入daodom树的指定位置中

    createRmCb当所有remove钩子触发完毕才会将节点从父节点移除

    相关文章

      网友评论

          本文标题:diff算法

          本文链接:https://www.haomeiwen.com/subject/vvdgohtx.html