当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用 “就地更新” 的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染(类似 Vue 1.x 的 track-by="$index")。
示例:下面通过一个例子来演示 “就地更新” ,代码如下:
<html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue</title> <!-- 使用 CDN 引入 Vue 库 --> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="(value,index) of items"> {{ index }} - {{ value }} </li> </ul> <p> <button type="button" @click="changeSequence">改变顺序</button> </p> </div> <script type="text/javascript"> var app = new Vue({ el: "#app", data: { items:[ 100, 200, 300 ] }, methods: { changeSequence: function(){ var t = this.items[1]; // 数组需要使用 Vue.set() 方式进行修改,才能触发 Vue 响应式渲染 // 如果使用 this.items[i] = n; 方式修改,不能触发 Vue 响应式渲染 Vue.set(this.items, 1, this.items[2]); Vue.set(this.items, 2, t); } } }); </script> </body> </html>
注意观察点击 “改变顺序” 按钮,数据发生改变,而 DOM 元素并没有发生移动,而仅仅修改 DOM 元素的内容。效果图如下:
Vue 默认的 “就地更新” 模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性,例如:
<div v-for="item in items" v-bind:key="item.id"> <!-- 内容 --> </div>
注意:
(1)建议在使用 v-for 时尽可能提供 key 属性,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
(2)不要使用对象(Object)或数组(Array)之类的非基本类型值作为 v-for 的 key,请使用字符串或数值类型的值作为 v-for 的 key。