关于v-for的一点小总结

简单介绍

在vue里面,咱们经过v-for指令来渲染一个数组列表,列表项须要咱们定义一个别名,即:html

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
复制代码

在上面这个例子中,items是咱们要渲染的数组列表,item是数组列表项的别名,固然,咱们能够给v-for添加第二个参数做为当前项的索引:vue

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ index }} - {{ item.message }}
  </li>
</ul>
复制代码

有经验的同窗可能会指出,上面的例子都少了一个属性: key,是的,官方文档建议咱们给v-for渲染的每个列表项指定一个key,那么,key的做用是什么呢?vue官方文档给了如下的解释:算法

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。若是数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每一个元素,而且确保它在特定索引下显示已被渲染过的每一个元素。这个相似 Vue 1.x 的 track-by="$index" 。数组

这个默认的模式是高效的,可是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。bash

为了给 Vue 一个提示,以便它能跟踪每一个节点的身份,从而重用和从新排序现有元素,你须要为每项提供一个惟一 key 属性。理想的 key 值是每项都有的惟一 id。这个特殊的属性至关于 Vue 1.x 的 track-by ,但它的工做方式相似于一个属性,因此你须要用 v-bind 来绑定动态值 (在这里使用简写):dom

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>
复制代码

建议尽量在使用 v-for 时提供 key,除非遍历输出的 DOM 内容很是简单,或者是刻意依赖默认行为以获取性能上的提高。由于它是 Vue 识别节点的一个通用机制,key 并不与 v-for 特别关联,key 还具备其余用途,咱们将在后面的指南中看到其余用途。ide

提出问题

问题1: 什么是'就地复用'?

这里我举一个简单的例子来讲明一下:性能

在一个玩具组装车间,小A, 小B, 小C,小D以及其余96个流水线工人一块儿完成组装玩具的工做,每一个人都有本身的一辆玩具在组装,忽然,小B肚子痛跑去上厕所了,可是小B的工做还没完成,为了避免影响总体进度,工人都依次往前补,小C顶替了小B的工做,小D顶替了小C的工做,以此类推,这样虽然也是有点麻烦,还好工做定期完成了。ui

这就是就地复用大概的思路,若是不采用就地复用,那么,当小B缺席以后,流水线上的工人(包括小B以前的)都要从新排序,100我的按照工号从新排序,从新获取本身的工做内容,这样子工做效率就大大下降了。this

在DOM中,就地复用的是那些没有变化的元素,例如:

<div v-for="item in items">
  <input/>
  {{item.message}}
</div>
复制代码

在这段代码中,没有变化的元素就是input,当咱们删除items的某个元素时,item.message会发生变化,所以渲染的数据发生了变化,可是已经存在dom中的input却会被就地复用,具体的演示效果以下:

问题2: 如何解决就地复用产生的问题?

正如咱们上面看到的那样,咱们但愿input也被从新渲染,这个问题的解决方案vue已经在文档中说的很清楚了,咱们须要给每个列表项加上一个惟一的key属性

问题3: key属性是如何解决问题的,它的原理是什么?

这个问题就涉及到了虚拟DOM的diff算法了,具体原理能够查看知乎的一篇文章

问题4: 没有添加key属性或者key属性不是惟一的会出现什么坑?

key属性须要绑定一个惟一的值,可是在咱们的实际项目中,不必定会有这么一个惟一的值让咱们绑定,所以习惯性咱们会采用index做为key属性的值,这样作就容易产生问题了...

由于index对应的value值是会变化的,例如:

list: [
  {index: 0, value: 0},
  {index: 1, value: 1},
  {index: 2, value: 2}
]
复制代码

当咱们执行list.splice(1, 1)移除index = 1的项时,list数组就会变成:

list: [
  {index: 0, value: 0},
  {index: 1, value: 2}
]
复制代码

由于index是数组元素的索引,当某个元素被移除时,被移除元素后面的元素索引都会更新,也就是说index并非惟一的,因此vue就会采用 就地复用 原则,这时若是页面上有相似于input这种跟value值没有绑定关系的元素时,这些元素将会被复用,有可能就得不到咱们要的效果了

总结: 相信用vue的人都会遇到这么一个列表渲染元素混乱的问题,key属性看似简单可是第一次遇到的时候是会很纳闷的,关于列表渲染比较常见的坑还有数组和对象的监测和更新,this.$set你值得拥有,详情能够查看官方文档,本文若是有错漏,欢迎指出~

相关文章
相关标签/搜索