vue的diff算法是如何实现的

diff算法

diff算法:

在之前的更新中,每次数据更新,在更新视图时,都是完全产生新的虚拟节点,通过新的虚拟节点生成真实节点,用新生成的真实节点替换所有的老节点。

这种方法在页面元素很少的情况下性能销毁倒是无所谓,但是在页面元素特别多情况下,很明显是消耗很大性能的。哪怕我只是修改了一个dom的文本内容,也都需要重新生成一遍所有节点。(因为现在只有一个组件)

第一次渲染的时候,我们会产生虚拟节点,第二次更新我们也会调用render方法产生新的虚拟节点,我们需要对比两次的vnode,找到需要更新的部分进行更新。

diff的实现,我是建立在前面的代码上的。
实现mini-vue之 computed,watch ,数组响应式的实现

没有key

对于没有key的情况下:vue会在两个vnode的tag相同的时候,就任务是同一个节点。这种情况下可能会出现错误复用。

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<!--更新后-->
<ul>
    <li>2</li>
    <li>3</li>
    <li>1</li>
</ul>

此时vue只会让第一个节点和第一个节点比较,第二个节点和第二个节点比较。

有key

vue在进行diff的时候(新旧虚拟dom都有子节点数组),维护了一个双指针,来进行比较。

// 我们为了比较两个儿子的时候,提高比较的性能(速度)
  /**
   * 1. 我们操作列表 经常会有 push pop shift unshift sort reverse 等方法 针对这些情况可以做一些优化
   * 2. vue2中采用双指针的方法 比较两个节点
   */
  let oldStartIndex = 0,
    oldEndIndex = oldChildren.length - 1,
    newStartIndex = 0,
    newEndIndex = newChildren.length - 1,
    oldStartVnode = oldChildren[oldStartIndex],
    oldEndVnode = oldChildren[oldEndIndex],
    newStartVnode = newChildren[newStartIndex],
    newEndVnode = newChildren[newEndIndex];
old head -> new head

新旧节点都进行头指针指向的头结点比较。如果两个子节点相同,则会进行复用。

<ul>
    <li key="a">1</li>
    <li key="b">2</li>
    <li key="c">3</li>
</ul>
<!--更新后-->
<ul>
    <li key="a">1</li>
    <li key="b">2</li>
    <li key="d">4</li>
</ul>

此时vue会复用前两个节点(比对后发现前两个节点都不需要更改),只需要在原来的dom元素上追加一个子元素而已。

old tail -> new tail

在头结点进行比较时,发现不是一个节点,则再次比较两个children的尾节点。

<ul>
    <li key="a">1</li>
    <li key="b">2</li>
    <li key="c">3</li>
</ul>
<!--更新后-->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尤雨东

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值