zoukankan      html  css  js  c++  java
  • vue diff算法讲解

    Source:https://zhuanlan.zhihu.com/p/81752104

    因为Vue在视图层上的更新是通过Virtual Dom实现的(直接操作Dom开销很大)。Virtual DOM是一个对象,每次更新视图层时可以直接比较新旧Virtual DOM上各节点的差异,只对出现变化的节点进行更新。这样可以减少更新量,降低资源消耗。查找节点变化的算法便是Diff算法。

    Diff 做法
    Vue 只会对新旧节点中 父节点是相同节点 的 那一层子节点 进行比较。也可以说成是,只有两个新旧节点是相同节点的时候,才会去比较他们各自的子节点。
    最大的根节点一开始可以直接比较。
    这也叫做 同层级比较,并不需要递归,虽然好像降低了一些复用性,也是为了避免过度优化,是一种很高效的 Diff 算法

    新旧节点是什么
    所有的 新旧节点 指的都是 Vnode 节点,Vue 只会比较 Vnode 节点,而不是比较 DOM,因为 Vnode 是 JS 对象,不受平台限制,所以以它作为比较基础,代码逻辑后期不需要改动,拿到比较结果后,根据不同平台调用相应的方法进行处理就好了。
    Vnode 更多信息:VNode - 源码版

    父节点是相同节点是什么意思?
    比如下图出现的 四次比较(从 first 到 fouth),他们的共同特点都是有 相同的父节点
    比如 蓝色方的比较,新旧子节点的父节点是相同节点 1
    比如 红色方的比较,新旧子节点的父节点都是 2
    所以他们才有比较的机会

    而下图中,只有两次比较,就是因为在 蓝色方 比较中,并没有相同节点,所以不会再进行下级子节点比较

    Diff 比较逻辑
    Diff 比较的内核是 节点复用,所以 Diff 比较就是为了在 新旧节点中 找到 相同的节点
    这个的比较逻辑是建立在上一步说过的同层比较基础之上的,所以说,节点复用,找到相同节点并不是无限制递归查找。
    比如下图中,的确 旧节点树 和 新节点树 中有相同节点 6,但是然并卵,旧节点6并不会被复用

    就算在同一层级,然而父节点不一样,依旧然并卵

    只有这种情况的节点会被复用,相同父节点 8

    下面说说 Diff 的比较逻辑

    1、能不移动,尽量不移动
    2、没得办法,只好移动
    3、实在不行,新建或删除
    

    比较处理流程是下面这样

    在新旧节点中
    
    1、先找到 不需要移动的相同节点,消耗最小
    
    2、再找相同但是需要移动的节点,消耗第二小
    
    3、最后找不到,才会去新建删除节点,保底处理
    

    比较是为了修改DOM树
    其实这里存在三种树,一个是 页面DOM 树,一个是 旧VNode 树,一个是 新 Vnode 树

    页面DOM树和旧VNode树 节点一一对应
    而新Vnode树则是表示更新后 页面DOM树 该有的样子
    这里把旧Vnode树和新Vnode树进行比较的过程中不会对这两棵Vode树进行修改,而是以比较的结果直接对 真实DOM 进行修改。
    比如说,在旧Vnode树同一层中,找到和新Vnode树中一样但位置不一样节点,此时需要移动这个节点,但是不是移动旧Vnode树中的节点,而是直接移动DOM。
    总的来说,新旧 Vnode 树是拿来比较的,页面DOM 树是拿来根据比较结果修改的。

    An Example
    比如下图存在这两棵 需要比较的新旧节点树 和 一棵 需要修改的页面 DOM树

    第一轮比较开始:
    因为父节点都是 1,所以开始比较他们的子节点
    按照我们上面的比较逻辑,所以先找 相同 && 不需移动 的点
    毫无疑问,找到 2


    拿到比较结果,这里不用修改DOM,所以 DOM 保留在原地

    第二轮比较开始
    然后,没有 相同 && 不需移动 的节点了
    只能第二个方案,开始找相同的点
    找到 节点5,相同但是位置不同,所以需要移动


    拿到比较结果,页面 DOM 树需要移动DOM 了,不修改,原样移动

    第三轮比较开始
    继续,相同节点也没得了,没得办法了,只能创建了
    所以要根据 新Vnode 中没找到的节点去创建并且插入
    然后旧Vnode 中有些节点不存在 新VNode 中,所以要删除

    于是开始创建节点 6 和 9,并且删除节点 3 和 4

    然后页面就完成更新啦

  • 相关阅读:
    MSsql bcp
    mssql 动态行转列。
    Ms sql 2000互转2005
    Ms sql pivot unpivot
    Ms sql将首字母大写
    java 进制相互转换
    Java 对字符反转操作。
    java jdbc 封装。。
    java SimpleDateFormat
    《more effective C++》条款10 防止构造函数里的资源泄露
  • 原文地址:https://www.cnblogs.com/Nullc/p/14538804.html
Copyright © 2011-2022 走看看