2/2 从一个简单例子来看 Vue.js 中 v-for 中 key 值的重要性

写在前面

  最近把基础都看了一下,在弄过渡的时候,将之前的知识串了起来,由此做了一篇小随笔

  在我的学习过程中,每每听到v-for视频里面的老师都说要加一个key值,有些时候不加其实也一样,为什么key这么重要呢?

  我来通过我的经验半吊子回答一下

1.就近复用

  就近复用,其实就是当用v-for的时,没有给定key值会发生的情况

  例如,我要通过 v-for 打印一个数组出来

  

  elements

·  

  那么这里面的每一个 < li > 标签 看似 是和 数组里面的数据 ” 一一对应 “了

  但是其实不是,因为没有 key 值 DOM和元素没有一一映射, 当数据发生改变时,Vue 是采取

    就近复用 来重新渲染的 DOM ( 没有 key 的情况下,一般来说 输出没有什么大变化 )

  

    key值是为了建立 值和 DOM节点的 映射关系 而方便进一步操作的 一个标志

  


  可能到这里还是会对 key 不是很清楚, 这里有一个 过渡 例子

 

 

2.过渡的 v-move

  

  1 <!DOCTYPE html>
  2 <html>
  3 
  4 <head>
  5   <title> </title>
  6 </head>
  7 
  8 <body>
  9   <style>
 10     .list-enter,
 11     .list-leave-to {
 12       opacity: 0;
 13     }
 14 
 15     .list-enter-active {
 16       animation: moveIn 1s;
 17     }
 18 
 19     .list-leave-active {
 20       animation: moveOut 1s;
 21       /* transition: all 1s linear; */
 22     }
 23 
 24     @keyframes moveIn {
 25       0% {
 26         opacity: 0;
 27         transform: translate(30px, 15px);
 28       }
 29 
 30       30% {
 31         opacity: 0.5;
 32         transform: translate(0px, 15px);
 33       }
 34 
 35       100% {
 36         opacity: 1;
 37         transform: translate(0, 0px);
 38       }
 39     }
 40 
 41     @keyframes moveOut {
 42       0% {
 43         opacity: 1;
 44         transform: translate(0, 0px);
 45       }
 46 
 47       30% {
 48         opacity: 0.5;
 49         transform: translate(0px, 15px);
 50       }
 51 
 52       100% {
 53         opacity: 0;
 54         transform: translate(30px, 15px);
 55       }
 56     }
 57 
 58     /* 重新随机排序用的是 move */
 59     .list-move {
 60       transition: all 1s;
 61     }
 62   </style>
 63   <div id="app">
 64     <button @click="addNewItem()">添加元素</button>
 65     <button @click="delNewItem()">删除元素</button>
 66     <button @click="orderByRandom()">随机排序</button>
 67     <br>
 68     <!-- tag 必须指定某个标签 而且里面的标签也必须要有KEY值 -->
 69     <transition-group name="list" tag="ul">
 70       <!-- <li v-for="item in list" :key="list.indexOf(item)"> -->
 71       <!-- 上面这样定义key值的话,就不会出现随机排序的动画效果 -->
 72       <li v-for="item in list" :key="item">
 73         {{ item }}
 74       </li>
 75     </transition-group>
 76   </div>
 77   <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
 78   <script type="text/javascript">
 79     // 声明 Vue 实例
 80     let vm = new Vue({
 81       el: '#app',
 82       data() {
 83         return {
 84           list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 85         }
 86       },
 87       methods: {
 88         addNewItem() {
 89           this.list.push(this.list.length)
 90         },
 91         delNewItem() {
 92           this.list.pop()
 93         },
 94         orderByRandom() { // 随机改变数组元素的位置
 95           let tmp = [] // 初始化新数组
 96           for (let i = 0; i < this.list.length; i++) {
 97             let num = Math.floor(Math.random() * (this.list.length - 0.001)) // 随机新元素
 98             // 当元素不在数组中时,将其加入到数组中
 99             let index = tmp.indexOf(num)
100             while (index !== -1) {
101               num = Math.floor(Math.random() * (this.list.length - 0.001))
102               index = tmp.indexOf(num)
103             }
104             tmp.push(num)
105           }
106           this.list = tmp // 更改list为新的数组
107         }
108       }
109     })
110   </script>
111 </body>
112 
113 </html>

 

  因为 transition-group 必须加 key , 这里就小技巧一下,70-71行

    <li v-for="item in list" :key="list.indexOf(item)">

  通过对赋值 key 为每一个元素的位置信息,当位置信息不改变时,就不会发生move动画

  可以f12调试一下

  因为 key 相当于一个身份信息,当这个身份信息没有发生改变的时候( list.indexOf(item) ),就不会发生move, 进行的只是数值的改变

    又因为,每一次的增加,减少 是对于位置的增加,减少,相应的 DOM也会如此,所以有过渡动画

  可见,key值的重要性 从根本上来说,是让 Vue 能够有迹可循追踪数据到相应的节点

  

 总结

  感冒了,好难受

 

 

  凭着意念弄了出来,继续加油

 

 

  

 

  ps: 敲代码是尤其重要的,看不出来别人的问题,只有自己实践了才会出现好多问题

Let it roll
原文地址:https://www.cnblogs.com/WaterMealone/p/14363184.html