语法格式:v-for 指令。该指令用在被遍历的标签上。

  1. v-for="(element, index) in elements" :key="element.id"

或者

  1. v-for="(element, index) of elements" :key="element.id"

2.6.1 遍历数组、对象、字符串、指定次数

1. 遍历数组

  1. <div id="app">
  2. <h1>{{msg}}</h1>
  3. <h2>遍历数组</h2>
  4. <ul>
  5. <li v-for="(product, index) in products" :key="product.
  6. id">
  7. 商品名称:{{product.name}},单价:{{product.price}}元/
  8. 千克,下标:{{index}}
  9. </li>
  10. </ul>
  11. </div>
  12. <script>
  13. const vm = new Vue({
  14. el : '#app',
  15. data : {
  16. msg : '列表渲染',
  17. products : [
  18. {id:'111',name:'西瓜',price:20},
  19. {id:'222',name:'苹果',price:10},
  20. {id:'333',name:'香蕉',price:30}
  21. ]
  22. }
  23. })
  24. </script>

运行效果:
image.png
2. 遍历对象

  1. <div id="app">
  2. <h1>{{msg}}</h1>
  3. <h2>遍历对象</h2>
  4. <ul>
  5. <li v-for="(propertyValue, propertyName) of dog" :key=
  6. "propertyName">
  7. {{propertyName}}:{{propertyValue}}
  8. </li>
  9. </ul>
  10. </div>
  11. <script>
  12. const vm = new Vue({
  13. el : '#app',
  14. data : {
  15. msg : '列表渲染',
  16. dog : {
  17. name : '拉布拉多',
  18. age : 3,
  19. gender : '雄性'
  20. }
  21. }
  22. })
  23. </script>

运行结果:
image.png
3. 遍历字符串

  1. <div id="app">
  2. <h1>{{msg}}</h1>
  3. <h2>遍历字符串</h2>
  4. <ul>
  5. <li v-for="char,index of str" :key="index">
  6. {{index}}:{{char}}
  7. </li>
  8. </ul>
  9. </div>
  10. <script>
  11. const vm = new Vue({
  12. el : '#app',
  13. data : {
  14. msg : '列表渲染',
  15. str : '动力节点'
  16. }
  17. })
  18. </script>

运行结果:
image.png
4. 遍历指定次数

  1. <div id="app">
  2. <h1>{{msg}}</h1>
  3. <h2>遍历指定次数</h2>
  4. <ul>
  5. <li v-for="number,index of 10" :key="index">
  6. 下标:{{index}},数字:{{number}}
  7. </li>
  8. </ul>
  9. </div>
  10. <script>
  11. const vm = new Vue({
  12. el : '#app',
  13. data : {
  14. msg : '列表渲染'
  15. }
  16. })
  17. </script>

运行结果:
image.png

2.6.2 虚拟 dom 和 diff 算法

所谓的虚拟 dom 就是内存当中的 dom 对象。vue 为了提高渲染的效率,只有真正改变的 dom 元素才会重新渲染。
image.png

2.6.3 v-for 的 key 的作用以及实现原理

1. 用 index 作为 key

  1. !DOCTYPE html>
  2. html lang="en">
  3. head>
  4. meta charset="UTF-8">
  5. title>key 的原理</title>
  6. script src="../js/vue.js"></script>
  7. /head>
  8. body>
  9. div id="app">
  10. <h1>{{msg}}</h1>
  11. <button @click="addFirst">在数组第一个位置添加 tom</button>
  12. <button @click="addLast">在数组最后位置添加 vue</button>
  13. <table>
  14. <tr>
  15. <th>序号</th>
  16. <th>姓名</th>
  17. <th>邮箱</th>
  18. <th>选择</th>
  19. </tr>
  20. <tr v-for="(vip,index) of vips" :key="index">
  21. <td>{{index + 1}}</td>
  22. <td>{{vip.name}}</td>
  23. <td>{{vip.email}}</td>
  24. <td><input type="checkbox"></td>
  25. </tr>
  26. </table>
  27. </div>
  28. <script>
  29. const vm = new Vue({
  30. el : '#app', 31. data : {
  31. msg : 'key 原理(虚拟 dom 与 diff 算法)', 33. vips : [
  32. {id:'100',name:'jack',email:'jack@123.com'}, 35. {id:'200',name:'lucy',email:'lucy@123.com'}, 36. {id:'300',name:'james',email:'james@123.com'}
  33. ]
  34. }, 39. methods : {
  35. addFirst(){
  36. this.vips.unshift({id:'400',name:'tom',email:'tom@123.com'})
  37. }, 43. addLast(){
  38. this.vips.push({id:'500',name:'vue',email:'vue@123.com'})
  39. }
  40. }
  41. })
  42. </script>
  43. </body>
  44. </html>

运行效果:
image.png
全部选中:

image.png
添加 tom:
image.png
可以看到错乱了。思考这是为什么?
2. 用 vip.id 作为 key
运行和测试结果正常,没有出现错乱。为什么?image.png
3. key 的作用
key 存在于虚拟 dom 元素中,代表该虚拟 dom 元素的唯一标识(身份证号)。
4. diff 算法是如何比较的?
新的虚拟 dom 和旧的虚拟 dom 比较时,先拿 key 进行比较:
(1) 如果 key 相同:则继续比较子元素:
1 子元素不同:直接将新的虚拟 dom 元素渲染到页面生成新的真实 dom 元素。
2 子元素相同:直接复用之前的真实 dom。
(2) 如果 key 不同:直接将新的虚拟 dom 元素渲染到页面生成新的真实 dom 元素。
5. index 作为 key 存在两个问题
(1) 效率较低。
(2) 对数组的非末尾元素进行增删时,容易错乱。
6. index 作为 key 和 vip.id 作为 key 对比
当 index 作为 key 时:
image.png
当 vip.id 作为 key 时:
image.png