在Vue文档中关于v-for指南模块有这么一段话:
那什么是就地更新策略呢?我们先来写一个案例,通过案例来介绍。
const app = {template: `<ul><li v-for="(item, index) of list"><span>{{ item.value }}</span><button @click="delteItem(index)">Del</button></li></ul>`,data(){return{list: [{id: 1,value: "item-1"},{id: 2,value: "item-2"},{id: 3,value: "item-3"}]}},methods: {delteItem(index) {this.list.splice(index, 1);}}}
以上代码,实现了一个简单的列表,然后通过按钮可以进行删除某项,效果如下:
点击删除 DOM 的变化
当我们删除item-2的时候看看会发生什么?
从上面的动态图中我们可以看到:我们删除的是**item-2**的**li**,第二个**li**里面的内容变成了**item-3**的内容,实际上删除的是第三个**li**(浏览器中紫色闪烁表示**dom**的内容发生了变化)。
这就是Vue的就地更新策略,回头看Vue文档的那句话:
:::info
Vue将使用一种最小化元素移动的算法,并尽可能地就地更新/复用相同类型的元素。
也就是说默认的情况下Vue会尽量使用已经存在的DOM元素,直接在已有的DOM上进行复用修改,这样可以带来一定性能上的提升。
:::
看一个更明显的案例:
const app = {template: `<div><div v-if="isLogin"><span>欢迎</span><a href="javascript:;" @click="isLogin = false">xiechen</a></div><div v-else><a href="javascript:;" @click="isLogin = true">登录</a><a href="javascript:;">注册</a></div></div>`,data(){return{isLogin: false}}}
以上代码,两个模块里都有a标签,按照我们的理解当条件发生变化的时候,div都会重新渲染,实际上Vue会进行就地更新策略。
可以很明显的看到第二个a标签一直在闪烁,也就是内容一直在更新而不是销毁重新创建的a标签!!!
就地更新的缺陷
再次回到Vue文档的那句话:
这又是什么意思呢?同样的我们还是用动态图要进行演示,我们把第一个案例进行改造,给每个li都新增一个input输入框:
<ul><li v-for="(item, index) of list"><span>{{ item.value }}</span><input type="text" /><button @click="delteItem(index)">Del</button></li></ul>

实际的效果有点让你疑惑,我明明删除的是item-2,为什么item-3的输入框内容却发生了变化?
:::info
这其实就是「就地更新」的缺陷!!!
因为input输入框是一个临时的状态,Vue无法判断节点的value到底有什么用,所以在删除item2的时元素会进行复用,input里的值也是会被保留的,实际删除的是第三个li及第三个li内的input。
:::
如何进行解决?
现在的问题就是Vue不会根据最新的顺去更新DOM,而是用已有的DOM进行属性的修改。
在这种情况下,我们需要给li标签绑定一个key属性,这样Vue就会根据最新的数据对DOM进行调整,而它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。
可以简单认为key是给每一个DOM节点一个唯一标识,这样Vue就不会启用就地更新了。
<ul><li v-for="(item, index) of list" :key="item.id"><span>{{ item.value }}</span><input type="text" /><button @click="delteItem(index)">Del</button></li></ul>

从图片中可以看到,加上key属性后item-2删除后,item-2的input也被删除啦。
key 的作用
简单说**key**的作用主要是为了更高效的对比虚拟**DOM**中每个节点是否是相同节点;
举个简单的例子:三胞胎战成一排,你怎么知道谁是老大?如果老大皮了一下子,和老三换了一下位置,你又如何区分出来?给他们挂个牌牌,写上老大、老二、老三。这样就不会认错了,key就是这个作用。
:::info
所以在使用key属性的时候需要注意,key属性必须是唯一的,不变的!当数据更新的时候,Vue可以通过key属性去确认元素,同时确认子元素是否要进行更新。
:::

