1

先说结论:使用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被渲染到了页面上,像下面这样:
image.png
然后,我们在控制台输入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>

会产生如下的问题:
image.png
同一个元素C,数据修改前C的index是2,修改后变成了3,使index和item不是一一对应的了。

必须要保证key和之后要展示的item是一一对应的

所以这里的key,我们使用item。因为item不会变。

vue会优先渲染有一一对应关系的,后渲染没有对应关系的。有对应关系的就不重复渲染了,从而提高了性能。


白话前端
109 声望8 粉丝