先说结论:使用v-for时,需要给元素或组件添加key属性。
加上key的目的:避免重复渲染
通过案例讲解。
案例:在字母列表 B 和 C 之间,插入 F
<div id="app">
<ul>
<li v-for="item in letters">{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['A', 'B', 'C', 'D', 'E']
}
})
</script>
实现方法
插入F方法:使用 splice
//浏览器运行代码后,在控制台输入
app.letters.splice(2,0,"F")
性能上的问题
先引入一个概念:diff算法。
vue会先把元素放到虚拟dom里,等代码段执行完(比如一个for循环执行完),vue会对比虚拟dom和真实dom的差别,然后只把不同的地方渲染到页面,这样就提高了性能。
在这个插入字母的案例中,for循环执行完了,ABCDE被渲染到了页面上,像下面这样:
然后,我们在控制台输入app.letters.splice(2,0,"F")
,改变了data,vue就会重新把输入都放入虚拟dom,再把虚拟dom和真实dom比对,只修改不同的地方,系统的地方不做修改。
但问题是:vue比对的时候发现,只有AB是一样的,别的都不一样。所以AB没动,别的都是被重新渲染到页面的。
这种方式并不高效。我们插入一个<li>F</li>
,是希望重新渲染的时候,只添加一个 F 即可,而不是把 FCDE 都替换。
解决方案
给节点增加key属性,来制作一个唯一的标识。
<li v-for="item in letters" key="item">{{item}}</li>
这个key的值,不能随意添加,必须要保证key和之后要展示的元素是一一对应的。
如果我们的key的值使用index:
<li v-for="item in letters" key="index">{{item}}</li>
会产生如下的问题:
同一个元素C,数据修改前C的index是2,修改后变成了3,使index和item不是一一对应的了。
必须要保证key和之后要展示的item是一一对应的。
所以这里的key,我们使用item。因为item不会变。
vue会优先渲染有一一对应关系的,后渲染没有对应关系的。有对应关系的就不重复渲染了,从而提高了性能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。