Vue中的key

在使用Vue开发项目中,如果使用循环渲染没有使用key的时候,vue会警告。但是这个key的作用是什么。

概念

在Vue官网中提到

建议尽可能在使用 v-for 时提供 kye,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。因为它是Vue识别节点的一个通用机制,key并不与 v-for 特别关联。

用 key 管理可复用的元素,Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外。

通过上诉可以大致了解 key 可以使 Vue 在复用时快速高效的渲染元素。

原理

Vue在渲染列表的时候采用就地复用的原则,如果改变了dom的顺序,那么vue不会对dom元素的顺序做修改,而是就此复用当前的元素

假设我们要在BC之间插入一个元素,如图所示

如果我们没有设置key的值那么 Vue 就会把整个列表重新渲染一变,得到如图结果

要是我们添加了key的话 Vue 会通过对先前 key 值配对的属性不会重新渲染一次,如图(左边没设置key,右边设置了key)

注意

key 值是唯一的,建议不要设置 index 为key值,导致的问题就是以前的数据和重新渲染后的数据随着 key 值的变化从而没法建立关联关系. 这就失去了 key 值存在的意义. 也是导致数据出现诡异的罪魁祸首!

Vue是不直接操作DOM的,是通过js的Object对象来模拟DOM中的节点,比较虚拟DOM是用的diff的算法。在同级A,B,C,D四个节点中,在B和C之间插入E,没有key的时候:C更新成了E,D更新成了C,最后插入D,这样效率很低。
加上key之后,就能准确的找到节点的位置:发现ABCD都没变化,直接插入E就可以了。
所以key的作用主要是为了高效的更新虚拟DOM

list:[
{
id: 1,
name: 'a',
//index: 0
},
{
id: 2,
name: 'b',
//index: 1
},
{
id: 3,
name: 'c',
//index: 2
},
{
id: 4,
name: 'd',
//index: 3
},
]

如上面的一串数组a,b,c,d,如果在b,c中间插入一个e

如果 key 绑定的是 index

那么除了a,b没有被改变之外,c,d的index发生了变化,所以c和d也都要重新渲染一遍,影响了性能

原理如图:

React中的key

React中如果没有指定 key 也会进行警告,和 Vue 为了提升渲染性能,在内部维持了一个虚拟dom,当渲染结构有所变化的时候,会在虚拟dom中先用diff算法先进行一次对比,将所有的差异化解决之后,再一次性根据虚拟dom的变化,渲染到真实的dom结构中。

key值是唯一的不建议使用 index 值。原理同上

简单示例,了解一下。等同于 Vue


import React, {Component} from 'react';
class Test extends Component {
constructor(props) {
super(props);
this.state = {
testArray: [{text: '组件1', id: 'a'}, {text: '组件2', id: 'b'}, {text: '组件3', id: 'c'}, {text: '组件4', id: 'd'}]
}
}

//修改state打乱顺序
sort(){
this.setState({
testArray: [{text: '组件1', id: 'a'}, {text: '组件3', id: 'c'}, {text: '组件2', id: 'b'}, {text: '组件4', id: 'd'}]
})
}

render() {
return <div>
<div>不指定key属性</div>
<ul>
{
this.state.testArray.map((item) => {
return <li ><span>{item.text}</span><input/></li>
})
}
</ul>
<div>指定key属性</div>
<ul>
{
this.state.testArray.map((item) => {
return <li key={item.id}><span>{item.text}</span><input/></li>
})
}
</ul>
<button onClick={::this.sort}>打乱排序</button>
</div>
}
}

export default Test

打乱前在iput中填入相应内容

打乱顺序后

我们可以观察一下,打乱顺序后,如果我们不指定key属性,列表中组件的标题打乱了,但是 input 里面的内容还是没有变,这是因为没有指定 key 打乱标题后重新对标题进行的渲染赋值。而指定了 kye 值且是唯一的时,React通过diff算法会根据 key 来进行匹配。