C# 移除JSON 某个key_vue中key的作用

摘要

本文结合源码说明了key的作用,给出了一个不写key的反例,并分析了原因。

内容

  • key的作用

  • 不写key会出的bug及原因分析

  • key的实践方案

key的作用

在数据变化前后,vue会得到两个虚拟dom树,并依次比较两个虚拟dom树中哪些结点有变动,从而决定去做具体的更新。这里有一个操作要做:比较两个结点是不是同一结点,这个操作在源码是通过sameVnode来完成的。见如下代码。

 // https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.jsfunction sameVnode (a, b) {  return (    a.key === b.key && (      (        a.tag === b.tag &&        a.isComment === b.isComment &&        isDef(a.data) === isDef(b.data) &&        sameInputType(a, b)      ) || (        isTrue(a.isAsyncPlaceholder) &&        a.asyncFactory === b.asyncFactory &&        isUndef(b.asyncFactory.error)      )    )  )}

假设我们给一组元素中的每一项都设置了一个唯一的标识,则a.key===b.key就可以更快地返回结果,这就是提升性能的关键点。

在实践中,渲染一组列表时,key往往是唯一标识(可能其它的条件是相同的),所以,如果不定义key,vue只能认为比较的两个节点是同一个 (undefined===undefined),哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能。有些特殊的时候甚至会有一些bug。

bug来了

下面这一段代码是硬编出来的,用它来说明如果在v-for循环中不写key,或者key没有正确使用会带来的后果。

 <div id="app" style="padding:20px">  <coma v-for="(it,idx) in list" :i="idx" @click="d">{{it}}coma>div><script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js">script><script>  Vue.component('coma',{    data() {      return {        v: Math.random()      }    },    template: `
-{{v}} 点我删除  
`,    props: ['i'] })  new Vue({    el: "#app",    data: {      list: [1, 2,3,4,5]   },    methods: {      d(idx) {        this.list.splice(idx, 1)     }   } })script>

bug描述:当在某一项上点击删除时,它会删除最后一项,而不是删除当前项(请把注意力放在最后一项)。

e190e7f3b8b9d90ab994b8410f710244.gif

原因分析

vue是通过虚拟dom来表示描述真实dom的,在去更新视图之前,要对前后两个虚拟dom树进行分析,以得出它们的区别。如果不设置key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。看官网 https://cn.vuejs.org/v2/api/#key

分析一下上面bug, 以在第2项上点击为例。

期待的情况,在点击前的数据:

 1,2,3

在点击之后的数据

 1,3 // 第二项被删除了。

但是由于没有设置key,此间产生的变化是:

  1. 把原来的第2项中的2改成3

  2. 把第3项删除掉。

所以会导致序号异常,且最后一项被删除了。

还有一个bug可以看这里https://codesandbox.io/s/vue-v-for-key-50x89。类似的情况还会发生在使用了v-transition时。

推荐设置key

可以通过如下的改进来避免上面的坑:

  1. 给列表中的数据项添加唯一的id

 data: {   list: [{id:1,value:1},{id:2,value:3},{id:3,value:3}]},
  1. 修改视图

 {{it.value}}

这样,在删除第二项时,vue会做出正确的判断:删除第二个组件。

小结

  • key的作用主要是为了更高效的对比虚拟dom中的某个节点是不是相同节点,是用来提高diff算法的性能表现。更具体一点,vue在patch过程(执行diff的算法,可翻译为打补丁算法)中判断两个节点是否是相同节点,key值相同是一个必要条件。

  • key会提升效率。某些特殊情况下,不写key会出错。

  • 在使用v-for循环时,尽量避免直接使用数组的下标为key,因为它们在做删除操作时可能会导致渲染异常。

  • 最好是将key设成数据项中的主键:可以把一项与另一项区别开的值。

版权信息:凡人进阶。转载请标明出处。如果对您有帮助,您可以:

  • 转发他人。

  • 小额打赏。

  • 关注本号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值