我们在使用vue开发时,经常会用到table、select options等组件,vue插件经常会提示我们在使用v-for遍历数组对象的时候要给template dom绑定key值。大多数人知道这个会提升性能,到底是什么性能呢?请往下看
二、官方解释
vue官方文档对key值的描述是这样的:
当 Vue 正在更新使用
v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个类似 Vue 1.x 的 track-by="$index"。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key attribute
:
<div v-for="item in items" v-bind:key="item.id"> // id不可重复且唯一
</div>
三、key作用
key值可赋值为:number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增)
dom diff为vue2.0新增的 性能优化点。
key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
首先,这个虚拟 DOM 算法是将VNode旧值和新值放在一起比对,感兴趣的同学可以去看看这篇文章详解vue的diff算法,写的是非常好的。
但是diff算法不是我这次要说的重点,重点是数组修改时触发的事件。
因为vue2.0数据绑定更新的方法是通过Object.defineProperty()设置get、set方法来实现的。
那么如果对数组设置呢?
跑下代码测试一下:
var arr = [
0, 1, 2, 3
Object.defineProperty(arr, "0", {
get() {
console.log('get 0');
return this._0 || 0;
set(newValue) {
console.log('set 0');
this._0 = newValue;
enumerable : true,
configurable : true
Object.defineProperty(arr, "1", {
get() {
console.log('get 1');
return this._1 || 1;
set(newValue) {
console.log('set 1');
this._1 = newValue;
enumerable : true,
configurable : true
Object.defineProperty(arr, "2", {
get() {
console.log('get 2');
return this._2 || 2;
set(newValue) {
console.log('set 2');
this._2 = newValue;
enumerable : true,
configurable : true
get 2
test.js:20 get 1
test.js:37 set 2
test.js:7 get 0
test.js:24 set 1
通过这个可以看到 由于数组在初始时就绑定了get、set方法,如果直接去做一次插值操作,会对每个属性都做一次卸载、安装的操作,这样在数组数据很大的情况下,是很费性能的。所以vue对此做了diff算法,根据old vdom和new vdom的数据结构来进行对比,通过对比节点类型、子节点值、子children diff、以及使用key来计算出最小的移动方案,从而使对dom的操作达到最小程度,可以大大提升性能。
- 412
-
老骥farmer
JavaScript
Vue.js
- 1.3w
-
耗子君QAQ
Vue.js
JavaScript