V3的diff算法

119 阅读3分钟

目前出去面试,动不动就问什么是diff算法,真想上去给他一下,这里浅浅的讲解一下

上一组代码,定义一个listinfo的数组,通过v-for循环遍历,将item渲染到页面,注意这个key值,是唯一的值,用这个key值来对比diff算法

<template>
  <div v-for="item in listinfo" :key>
    {{ item }}
  </div>
</template>

<script setup lang="ts">
const listinfo:number[] = [1, 3, 5, 7]

</script>

首先,我们在原基础是增加或者减少属性,操作don,在索引为2的数值上插入一个增加

const listinfo:number[] = [1, 3, 5, 7]
listinfo.splice(2, 0, '增加')// 1 3 增加 5 7

没有key值的diff算法,分三步,讲的就是旧的Vnode和新的Vnode做对比,可以打开源码看一下,git地址,首先通过for循环去patch,就是重新渲染我们这个元素,然后就是删除,最后就是新增一共分三步,画图说一下

Snipaste_2023-06-03_09-21-00.png

第一步就是做替换的,新旧的Vnode去做对比,数字1新的Vnode会把旧的Vnode替换掉,数字3也是替换掉,第三个是我新增的,也是替换掉,数字5把7替换掉,最后发现新Vnode是多的

到了第二步,新增,新Vnode会多出来的原因,diff算法就算完成了

第三步,删除,新Vone的值少了就进行删除的操作

但是我们发现 新旧Vnode值有的是一样的,这种的可以复用,不需要再重复的进行操作,这就是有key的值的好处,每一个相当于做了标记,下面来说一下有key值的diff算法

有key值的diff算法,这个步骤多了一点,分为五步

  • 进行一个前序算法,通过isSaneVnodeType去判断type和key是不是一样的,一样的就复用,type就是比如我们现在渲染的元素是一个div,那type就是div,key值就是我们绑定在div上面的唯一元素,下面图我们发现1和3是一样的,走的就是
  • 进行一个前序算法,通过isSaneVnodeType去判断type和key是不是一样的,一样的就复用,type就是比如我们现在渲染的元素是一个div,那type就是div,key值就是我们绑定在div上面的唯一元素,下面图我们发现1和3是一样的,走的就是前序算法

Snipaste_2023-06-03_09-39-43.png

  • 尾序对比,当发现5和新增是不一样的时候,就从后面先开始对比,i--的方式去做的对比,7和7, 5和5

前面两个就是头和头,尾和尾做的对比,和V2的diff算法有点区别,不再做交叉的对比

  • 新增,5和新增是不一样的时候,开始做一个patch
  • 删除,新Vnode值对比少的时候,就开始进行删除
  • 乱序,当我们操作dom的时候,新增删除替换等一系列乱序操作的时候,就开始进行第五步的操作,大概说一下,利用绑定的key值,数值怎么变,key值是不变的,新旧ken值做比较,多余的就删除,缺失的就新增