Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
运行出现迭代中的元素没有绑定key指令错误
我们先来聊聊
1、V-for的作用
将一个数组遍历或枚举一个对象属性的时候循环显示渲染页面
2、一定要加key吗?
对于用v-for渲染的列表数据来说,数据量可能一般很庞大,而且我们经常还要对这个数据进行一些增删改操作。假设我们给列表增加一条数据,整个列表都要重新渲染一遍,那不就很费事了。
3、而key的作用
- 为了提高渲染性能。
当元素位置发生改变时 vue 不会对整个列表进行重新渲染,而只是更换一下 虚拟DOM 的顺序,这样可以减少资源消耗
4、index(即数组的下标)
写key时,我就统一的都把index索引作为key,然后接着开发,就像下面这样:
<h1 v-for="(item, index) in items" :key="index">{{ item.title }}</h1>
v-for默认是通过index索引来追踪变化,通过追踪index索引,Vue观测列表中的项目的顺序变化,并在顺序发生变化时,就地修改每个项目。
Vue文档中指出,“这个默认的index模式是高效的”,但是像Vue文档所说的那样,我们要尽可能使用数据的唯一ID来做每个元素的key,这样 Vue 可以更准确地追踪数组中项目的更改并更新组件状态,并且能够重用和重新排序现有组件,而不必重新渲染整个循环。
举个例子
- 在数组后面追加一条数据
list = [
{
id: 1,
num: '1'
},
{
id: 2,
num: 2
},
{
id: 3,
num: 3
},
{
id: 4,
num: '新增加的数据4'
}
];
此时前三条数据页面不会重新渲染,直接复用之前的,只会新渲染最后一条数据,此时用index作为key,没有任何问题。
- 在数组中间插入一条数据
list = [
{
id: 3,
num: 1
},
{
id: 4,
num: '新增加的数据4'
},
{
id: 2,
num: '2'
},
{
id: 3,
num: '3'
}
];
页面在去渲染数据的时候,通过index定义的key的比较,会有:
之前的数据 之后的数据
key: 0 index: 0 num: 1 key: 0 index: 0 num: 1
key: 1 index: 1 num: 2 key: 1 index: 1 num: '新增加的数据4'
key: 2 index: 2 num: 3 key: 2 index: 2 num: 2
key: 3 index: 3 num: 3
通过上面清晰的对比,发现除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染。
4.2、此时我们用id作为key值
list = [
{
id: 1,
num: 1
},
{
id: 4,
num: '新增加的数据4'
},
{
id: 2,
num: 2
},
{
id: 3,
num: 3
}
];
之前的数据 之后的数据
key: 1 id: 1 index: 0 num: 1 key: 1 id: 1 index: 0 num: 1
key: 2 id: 2 index: 1 num: 2 key: 4 id: 4 index: 1 num: '新增加的数据4'
key: 3 id: 3 index: 2 num: 3 key: 2 id: 2 index: 2 num: 2
key: 3 id: 3 index: 3 num: 3
现在对比发现只有一条数据变化了,就是id为4的那条数据,因此只要新渲染这一条数据就可以了,其他都是就复用之前的。
key加索引index,id的作用
- key属性可以避免数据混乱的情况出现。
推荐使用id
6、v-for渲染原理
-
1.vue实现了一套虚拟DOM,使我们可以不直接操作DOM元素只操作数据,就可以重新渲染页面,而隐藏在背后的原理是高效的Diff算法
-
2.当页面数据发生变化时,Diff算法只会比较同一层级的节点;
-
3.如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点后面的子节点;如果节点类型相同,则会重新设置该节点属性,从而实现节点更新
-
4.使用key给每个节点做一个唯一标识,Diff算法就可以正确失败此节点,"就地更新"找到正确的位置插入新的节点。
了解可以看看Diff详解