Key

Vue中每次列表循环为什么要添加key值

vue中的key主要用来标记元素,当VNode更新的时候,会把旧的VNode和新的VNode进行对比:

1.新VNode和旧VNode都存在的相同key元素会被复用。

2.旧VNode中存在而新VNode不存在的key元素会被移除。

3.新VNode存在而旧VNode不存在的会key被添加。

不添加key值会怎样

1
2
3
4
5
<ul>
<li key="A">A</li>
<li key="B">B</li>
<li key="C">C</li>
</ul>

1.对于上面的列表渲染,我们进行两个操作:

(1)给尾部添加一个新元素D。

(2)在A后面添加一个新元素D。

2.若不添加key值,Vue会采用就地复用的原则。

(1)对于操作1,前面三个元素会被复用,然后新增一个元素D

(2)对于操作2,前面三个元素会被复用,但会把B元素的文本替换为D,C元素的文本替换为B,然后新增一个元素,文本为C.

3.对于添加key值,Vue会对元素进行前后对比。

(1)对于操作1,由于前面三个元素在更新前后key一样,所以会被复用,直接新增一个元素D

(2)对于操作2,Vue检测到A、B、C三个元素key在更新前后都存在,所以这三个元素还是会被复用,直接新增一个元素D插入到A后面即可。

添加key值的性能更优?

对于上面的代码,操作1无论有无key值,性能都差不多,但对于操作2,明显添加key值的情况会更好,所以添加key值一定优于不添加key值?

看下面代码:

1
2
3
4
5
6
// DOM1
<ul>
<li key="A">A</li>
<li key="B">B</li>
<li key="C">C</li>
</ul>
1
2
3
4
5
6
// DOM2
<ul>
<li key="D">D</li>
<li key="E">E</li>
<li key="F">F</li>
</ul>

若由DOM1更新到DOM2:

1.不添加key值,由于就地复用,所以三个元素会被复用,直接更改文本即可。

2.对于添加key值,由于前后key值不一样,所以会直接删除A、B、C三个元素,新增三个元素D、E、F。

这种时候,不添加key值的情况性能反而更好。

为什么要使用key值?

1.前面所列举的示例都是简单模板,当列表数据很长时,往往就地复用的性能不如添加key值的情况。

2.若不使用key值,可能会影响列表的状态。

比如,我们经常会把一个列表的索引当作key,而官方是不推荐把索引当key值的,为什么?

还是回到刚才的列表渲染,若现在我们给每个元素前新增一个复选框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul>
<li key="A">
<input type="checkbox" />
<label>A</label>
</li>
<li key="B">
<input type="checkbox" />
<label>B</label>
</li>
<li key="C">
<input type="checkbox" />
<label>C</label>
</li>
</ul>

现在进行如下操作:把三个复选框全部打勾,然后往A后面插入一个新元素D。

1.若添加了key,操作完会发现A、B、C仍然打勾,D没打勾,这是正确的逻辑。

2.若不添加key,操作完会发现A、D、B打勾,而C不打勾,这时候bug就出来了,原因就是不添加key值元素会就地复用,所以A、B、C所在元素包括复选框的状态被复用了,所以更改之后,默认还是前面三个元素打勾。

总结

1.不带key值时,对于简单渲染而言,性能会更好,但这并不是key的作用。

2.key的作用:

(1)更准确。避免出现状态错误的情况。

(2)更快。提升diff时同级比较的效率。