vue diff

虚拟DOM通过将DOM转换为JS对象实现高效更新,减少不必要的DOM操作。当数据变化时,新旧虚拟DOM对比找出差异,仅更新必要部分。虚拟DOM的优缺点包括性能优化、跨平台支持及额外的创建函数需求。更新流程涉及Diff算法,key用于区分可复用节点,避免错误的节点复用问题。v-for使用key确保每个元素唯一,确保列表更新正确。
摘要由CSDN通过智能技术生成

虚拟dom

  • 把Dom抽象成js对象来表示。
  • 当页面数据变化,将新虚拟dom和旧虚拟dom比对,得出差异,然后只修改差异部分,局部更新,减少重复创建渲染相同dom的损耗
  • 直接操作dom是要比虚拟dom快很多的,但是当节点很多,需要局部更改,虚拟dom可能是最优的,可以说虚拟dom是一种性能损耗和时间之间比较平衡的方法

虚拟dom优点:

  • 减少不必要的dom操作
  • 跨平台(本质就是js对象模拟了dom)

虚拟dom缺点:

  • 需要额外的创建函数如vue的h函数和react的creatElement函数
  • 如何解决?:
    • react有jsx,vue有template,但是这两个的缺点就是需要额外的构建过程,把它转换为标签。

更新流程

Dep.notify通知watcher进行更改

patch()

  • patch()
  • 对比新旧两个虚拟节点
  • 如果没有旧节点,直接插入新节点
  • 如果没有新节点,直接删除旧节点
  • 如果新旧节点都存在
    • 使用sameVnode函数进行比对,看是否为可比较节点(是否相同)
      • key是否相同
      • tag是否相同
      • 是否都为注释节点
      • 是否都定义了data(不在意data是否相同)
      • inoput的type是否相同
    • 相同:调用patchVnode进一步处理
    • 不同:直接删老添新

patchVnode

  • 两者一模一样(dom节点的引用判断),直接返回
  • 两者在生命周期created和beforemount间变为AST后,被优化时标记为了静态节点,并且两者key相同,则直接吧旧节点赋给新节点,然后返回
  • 如果新节点是文本节点,直接设置进真实dom里
  • 如果不是文本节点,进行以下比对
  • 如果都有孩子节点且孩子节点不同,调用updateChildren函数进行孩子更新
  • 如果只有新孩子,若旧节点有文本节点,删除,插入新节点的孩子节点
  • 如果只有旧孩子,移除旧孩子

updateChildren

  • 设置四个指针,指向旧节点头尾,新节点头尾
  • while循环比对,四个指针向中间靠拢,当旧尾小于旧头或新尾小于新头,结束循环
    • (旧节点先结束,说明新节点有需要插入的系内容;新节点先结束,说明旧节点有需要删除的旧内容)
    • 旧头新头,比对成功,两者指针+1,向中间靠拢
    • 旧尾新尾,比对成功,两者之间-1,向中间靠拢
    • 旧头新尾,比对成功,旧头+1,新尾-1,向中间靠拢
    • 旧尾新头,比对成功,旧尾-1,新头+1,向中间靠拢
    • 四种情况都没成功
      • 根据旧节点生成key与value的map
      • 新头的key在map中是否有对应的key
      • 对应成功,移动旧节点中匹配上的,新头+1
      • 未成功,生成新节点并插入,新头+1

在这期间,判断两者相同还是用sameVnode,改变两者还是用patchVnode

v-for为什么用key标识

在标签为li情况下:
根据updateChildren函数,如果无key,即都为undefined,则每次比较时key都相同(sameVnode认为两者相同),则会进入深入处理的patchVnode函数,然后把两者内部的文本进行替换,复用当前的li元素。
假设:A B C D变为A B E C D
则A,B不变,当到E时,发现E与C的key一样(undefined),进入patchVnode函数,会直接把E内的文本替换到C内,这就导致E根本不是E,而是换了文本的C(换皮了,根没变),这就会导致一些错误(你选择了E,其实你选的还是C)
在这里插入图片描述
而加上了key,每个li都有自己的key
假设:A B C D变为A B E C D
A,B同,到E时,不满足E等于C(key不同),则变道第二种比对(旧头旧尾),然后最后发现旧节点先结束,说明新节点中E多余,是新插入的,则生成E再插入,这样就对了
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值