注册
web

记一次不规范使用key引发的惨案

前言


平时在使用v-for的时候,一般会要求传入key,有没有像我一样的小伙伴,为了省心,直接传索引index,貌似也没有遇到过什么问题,直到有一天,我遇到一个这样的需求


场景


在一个下单界面,我需要去商品列表选商品,然后在下单界面遍历显示所选商品,要求后选的排在前面,而且选好商品之后,需要在下单界面给每个商品选择发货地,发货地列表是通过商品id去接口取的,我的代码长这样:



  • 下单界面调用商品组件

// 这里每次选了商品都是从前插入:list.value = [...newList, ...list.value]
<Goods
v-for="(item, index) in list"
:key="index"
:goods="item">
</Goods>


  • 商品组件内部调用发货地组件

<SendAddress
v-model="address"
:product-no="goods.productNo"
placeholder="请选择发货地"
@update:model-value="updateValue"></SendAddress>


  • 发货地组件内部获取发货地址列表

onMounted(async () => {
getList()
})
const getList = async () => {
const postData = {
productInfo: props.productNo,
}
}

上述代码运行结果是,每次获取地址用的都是最开始选的那个商品的信息,百思不得其解啊,最后说服产品,不要倒序了,问题解决


解决过程


后来在研究前进刷新后退缓存时,关注到了组件的key,详细了解后才知其中来头


企业微信截图_16813558431830.png



重点:根据key复用或者更新,也就是key没有变化,就是复用,变化了在更新挂载,而onMounted是在挂载完成后执行,没有挂载的元素,就不会走onMounted



回到上述问题,当我们每次从前面插入数据,key的变化逻辑是这样的


结论


企业微信截图_16813564053499.png



最开始选中的商品key从1变成了2,最近选的是0。


而0和1是本来就存在的,只会更新数据,不会重新挂载,只有最开始选的那个商品key是全新的,会重新挂载,重新走onMounted。


所以每次选择数据后,拿去获取地址列表的商品信息都是第一个的



解决以上问题,把key改成item.productNo就解决了


作者:赖皮喵
来源:juejin.cn/post/7221357811287834680

0 个评论

要回复文章请先登录注册