v-for 中 key 的作用

想要搞清楚v-for中key的作用,首先要了解虚拟DOM和diff算法。

一、虚拟 DOM

虚拟DOM,简称VNode,其实是一颗以 JavaScript 为基础的树,是对真实DOM的抽象。虚拟 DOM 可以经过一系列转换变为真实 DOM 并渲染到页面上。
可以用虚拟 DOM 来描述一个简单的 Vue 组件:

<template>
	<span class="demo" v-show="isShow">This is a span.</span>
</template>

对应的 VNode:

{
  tag: 'span',
    data: {
    directives: [
      {
        rawName: 'v-show',
        expression: 'isShow',
        name: 'show',
        value: true
      }
    ],
      staticClass: 'demo'
  },
  text: undefined,
    children: [
      {
        tag: undefined,
        data: undefined,
        text: 'This is a span.',
        children: undefined
      }
    ]
}

二、diff 算法

假设现在已经有一颗 VNode 树,现在又有一颗 VNode 新树,现在需要把最新的这颗树更新上去要怎么操作呢?
最简单粗暴的方式就是拿最新的树把之前的树替换掉,然后重新渲染页面,这样确实可以解决问题,但肯定不是最佳解决方案。我们肯定要思考能不能只更新变化的部分,那些没有变化的元素不更新,这样不是更高效吗?
要想实现这种高效的方法,我们需要找到两棵树中变化的部分进行更新,而 diff 算法就是来解决这个问题的。

三、v-for 中的 key

官方文档的解释:

当Vue正在使用 v-for 来渲染元素列表时,它默认使用“就地更新”的策略,如果数据项的顺序被改变,Vue 不会移动 DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态(例如:表单输入值)的列表渲染输出
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一 key 。

不使用 key 的代码:

<template>
	<ul>
		<li v-for="item in arr">{{item}}</li>
	</ul>
</template>
<script>
	export default {
		data() {
			arr: ["A", "B", "C"],
		},
		created() {
			setTimeOut(() => {
				this.arr.splice(1, 0, "D");
			}, 2000);
		}
	}
</script>

上面的代码就是把数组 [A, B, C] 变为 [A, D, B, C],同时页面也更新,diff过程如下图:
v-for 中 key 的作用_第1张图片
一共做了两次更新,一次插入操作。
接下来再看有 key 的情况:

<template>
	<ul>
		<li v-for="item in arr" :key="item">{{item}}</li>
	</ul>
</template>
<script>
	export default {
		data() {
			arr: ["A", "B", "C"],
		},
		created() {
			setTimeOut(() => {
				this.arr.splice(1, 0, "D");
			}, 2000);
		}
	}
</script>

v-for 中 key 的作用_第2张图片
在有 key 的情况下,只进行了一次插入操作。
因此,v-for 中 for 的作用就是让每个被循环的元素都有一个唯一的身份标识,这样 Vue 就可以更加精准的追踪到每个元素,从而更加高效的更新页面,当然,如果没有 key 程序也不会报错,只不过此时,程序的效率会很低。

你可能感兴趣的:(笔记,Vue,javascript,前端,vue.js)