美文网首页Vue技术
关于vue和React的diff算法以及key的用途

关于vue和React的diff算法以及key的用途

作者: darkTi | 来源:发表于2022-04-12 02:53 被阅读0次
    • 在使用Diff算法比较两个节点的时候,只会在同层级进行比较,而不会跨层级比较(也就是说只会在拥有相同爸爸的子节点中进行对比)

    这次我们先说结论,两者有什么区别
    1、children节点对比时,React是从左到右遍历对比,vue是从双端交叉进行对比;
    2、Vue的整体效率会比React高一些,比方说这个场景下:加入有多个子节点,我只是把最后一个节点移到了第一个
    ①React是需要借助 Map来匹配key,再复用节点;
    ②Vue会发现移动,直接去复用节点;

    Vue diff

    patchVnode
    • 相同节点就调用patchVnode(oldVnode, vNode),下图是它的流程:
      patchVnode.png
    • 除了比较子节点的方法updateChildren(elm, oldCh, ch)与React不同,其余都差不多,都是从根节点属性、文本节点、孩子节点比较下来的;
    updateChildren(elm, oldCh, ch)
    • 它就是Vue diff的核心了,【双端交叉对比法】,首先这个方法传入三个比较重要的参数,即parentElm父级真实节点;oldCh为oldVnode的孩子节点;newCh为Vnode的孩子节点。
    • 它每次按照下面5个步骤,来移动四个指针,直到有一组指针重叠并越过,则对比结束;
      ①头头对比;②尾尾对比;③旧头新尾对比;④旧尾新头对比;⑤通过key值对比;
    • 同样,找到相同的节点就调用patchVnode(oldVnode, vNode),对这个节点进行patch;

    React diff

    1、首先对比两棵树的根节点
    i. 如果根节点的类型改变了,比如 div 变成了 p,那么直接认为整棵树都变了,不再对比子节点。此时直接删除对应的真实 DOM 树,创建新的真实DOM 树。
    ii. 如果根节点的类型没变,就看看属性变了没有
    a. 如果没变,就保留对应的真实节点
    b. 如果变了,就只更新该节点的属性,不重新创建节点。

    2、然后同时遍历两棵树的子节点,从左到右遍历对比(这就是与vue的双端交叉对比不同的地方),每个节点的对比过程同上。
    ⅰ. 当子节点上都没有key的时候,那么每个节点的对比过程与跟节点的对比过程一致;
    ⅱ. 当子节点上有key的时候
    它会把变化的那个节点以及后面的节点全部暂存在map里,后面的节点就先从桶里进行key的匹配,没有匹配到的节点就创建它,匹配到就复用,有key剩下来了就删除它

    对于key的用途

    • key在vue和react中的用途是一致的,都是为了给元素绑定一个唯一的标识,用于判断元素是新创建的还是被移动的元素,从而减少不必要的DOM渲染;
    • key值一般不要用index来辨识,最好用唯一的id值来标识;因为如果用index做key值,那么修改list后,随着页面的重新渲染,key值可能就会发生变化,那么我们就失去了使用key值的意义了;
    • 但是!!当有很多分页的纯数据列表展示页面时,用index做key值会好一些,这样每页的元素都不需要销毁重建了,可以直接复用;

    相关文章

      网友评论

        本文标题:关于vue和React的diff算法以及key的用途

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