我们在使用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
// console
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的操作达到最小程度,可以大大提升性能。

分类:
前端
  •