vue循环key的问题

前言

记一下最近面试中被问到关于如果vue中循环不加key有什么问题


问题

首先我们有一点肯定知道,就是设置key可以优化diff算法,(这里看vue3代码),vue3对没有key的更新是执行patchUnkeyedChildren函数
代码节选

// 旧子节点
c1 = c1 || EMPTY_ARR
    // 新子节点
    c2 = c2 || EMPTY_ARR
    const oldLength = c1.length
    const newLength = c2.length
    const commonLength = Math.min(oldLength, newLength)
    let i
    for (i = 0; i < commonLength; i++) {
      const nextChild = (c2[i] = optimized
        ? cloneIfMounted(c2[i] as VNode)
        : normalizeVNode(c2[i]))
      patch(
        c1[i],
        nextChild,
        container,
        null,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized,
      )
    }

上面代码是vue3的源码,会发现如果没有key的话,就是全量替换,但真实情况可能不需要全量替换,这是加key一种优化

还有一个问题就是不加key的问题,看下面代码

<template>
    <div>

        <ul>
            <button @click="add">add</button>
            <li v-for="(item,index) in list" >
                <input type="checkbox" >
                {{ item.name }}
            </li>
        </ul>
    </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const list = ref([
    { name: '小张',id:1},
    { name: '小七',id:2},
    { name: '小三',id:3},
])
const add = () => {
    list.value.unshift({name:'小五',id:4})
}
</script>
<style lang='scss' scoped></style>

页面非常简单
在这里插入图片描述
当我们选择第一项的时候,如果再点击添加的时候会发现下面这种情况
在这里插入图片描述
在这里插入图片描述
会发现选中的是第一个,而不是小张(用索引当key也是一样),是因为底层此时是用循环索引判断,对于一开始的来说选中的是索引为0,添加之后小五是索引为0的,所以选中小五(key用索引同理),但是当key使用id的话,再看结果
在这里插入图片描述
就发现结果是我们想要的,这是因为此时id唯一值,而我们发现源码中计算有key的时候执行

 while (i <= e1 && i <= e2) {
      const n1 = c1[i]
      const n2 = (c2[i] = optimized
        ? cloneIfMounted(c2[i] as VNode)
        : normalizeVNode(c2[i]))
        # 判断两个节点是否一样,一个是type(标签类型)一个是key
      if (isSameVNodeType(n1, n2)) {
        # // 节点相同 
        patch(
          n1,
          n2,
          container,
          null,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized,
        )
      } else {
        # // 相同前置节点(a b)的更新处理完成
        break
      }
      i++
    }

isSameVNodeType函数是判断key值和标签类型,如果一样才会替换,否则不进行替换,所以上面选择是没有问题的

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值