记录-记一次不规范使用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,详细了解后才知其中来头
重点:根据key复用或者更新,也就是key没有变化,就是复用,变化了在更新挂载,而onMounted是在挂载完成后执行,没有挂载的元素,就不会走onMounted
回到上述问题,当我们每次从前面插入数据,key的变化逻辑是这样的
结论
最开始选中的商品key从1变成了2,最近选的是0。
而0和1是本来就存在的,只会更新数据,不会重新挂载,只有最开始选的那个商品key是全新的,会重新挂载,重新走onMounted。
所以每次选择数据后,拿去获取地址列表的商品信息都是第一个的
解决以上问题,把key改成item.productNo就解决了