先来看下key的介绍:
key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速
为什么会更快速,更准确呢,下面来看vnode中关于节点更新复用的详情情况
在diff中比较两个节点是否可以复用,主要通过下面sameVnode函数来判断
- key:列表上每一项设置的key值
- data:render函数中设置的一些属性
- sel:标签和id或者class,例如 div#app.item,表示div标签有一个id:app,class:item
当我们没有设置key值的情况
默认是undefined,undefined===undefined = true
因为是列表,所以标签,class,属性基本上是一样,只是里面内容不一样,通过调用上诉函数,可以判断出:可以复用的dom
我们来设想一下,如果我们有一个列表,然后我们在列表的头部新增一条数据
1、首先会比较新增的vnode和老元素第一个元素比较,因为sameVnode返回true,标签可以复用,修改里面的内容
2、比较第二个元素,是不是sameVnode返回的还是true,标签复用,修改列面的内容,以此类推,是不每一个节点都要替换内容
3、如果我们列表每一项有一个chekbox元素,勾选的第一项,再插入新元素的时候,是不是你插入的节点被勾选了,这样是不是就不对了,有问题
4、而且每一个元素都替换,是不是特别慢,并且列表需要全部重新渲染,大大的影响的性能
如果设置了key,key值是index的情况
把key值设置成index,有什么问题吧,为什么说最好不要设置成index
1、列表每一项设置了一个index值,从0、1、2、3、4、5
2、当我们在头部插入一个节点,是不是插入的节点就变成0,原来的0、1、2、3、4都加一位,我们来diff比较的时候,是不是每一项又都不一样了,sameVnode返回的都是false,标签不能复用,都要重新创建一个,插入到节点中,这样是不是也全部需要重新渲染,影响性能
如果设置了key,且key值固定的情况
下面我们来把key设置成唯一的值,且是固定的值,当我们在头部插入一个节点,这个节点的key没有一样的,我们就创建一个,插入到头部
后面的节点,是不是sel没有变,标签没有变,key值也没有变,是不是节点全部都可以复用,只是把位置挪动下,实际上就只创建了一个元素,这样就可以大大加快渲染速度
这就是我们所说的diff操作更加准确,更快速的原因