Vue3+Pinia:store更新后子组件未同步更新问题排查
问题根因
两个异常都是响应式连接断开、代码写法不规范导致的,具体对应原因:
- 父组件给子组件绑定事件时写法错误:
@quantity-event="(n) => quantity = n"中quantity是ref类型,直接给变量本身赋值数字,会把原本的响应式ref对象覆盖为普通数值,后续修改值无法触发视图更新;父组件执行quantity.value = 1重置值时,因为响应式已经被破坏,自然无法同步给子组件。 - 子组件仅在初始化时将props的
quantity拷贝到本地count变量,没有监听props的后续变化,父组件修改传入的quantity值时,子组件本地的count不会同步更新。同时子组件中emit的定义在事件函数之后,const声明不存在变量提升,会触发暂时性死区报错,属于隐藏bug。 - Pinia store中直接持有外部传入的商品对象引用,还直接给外部传入的对象新增
quantity属性,既违反了Vue单向数据流原则,也容易因为外部对象非响应式、引用污染导致状态更新后视图不刷新。
修复步骤
按照以下顺序修改代码即可解决所有问题:
- 修正父组件的事件绑定写法
父组件模板中计数器组件的事件回调要给ref的.value赋值,避免覆盖ref对象:<counter-input :quantity="quantity" @quantity-event="(n) => quantity.value = n"></counter-input> - 修正子组件的响应式同步问题
调整子组件代码顺序,新增对props的监听,确保父组件传入的值变化时本地计数同步更新:<script setup> import {ref, watch} from "vue" // 先定义emit,避免暂时性死区报错 const emit = defineEmits(['quantityEvent']) const props = defineProps({ quantity: { type: Number, required: true } }) const count = ref(props.quantity) // 监听父组件传入的quantity变化,同步到本地计数 watch(() => props.quantity, (newVal) => { count.value = newVal }) const increase = () => { count.value++ emit('quantityEvent', count.value) } const decrease = () => { if(count.value === 1) return count.value-- emit('quantityEvent', count.value) } </script> - 修正Pinia store的状态更新逻辑
存入新商品时创建对象副本,不要直接持有外部对象引用,避免状态污染:import { defineStore } from 'pinia' import axiosClient from '@/axios' export const useTableOrderStore = defineStore( 'tableOrders', { id : 'tableOrders', state: () => ({ tableOrders: [] }), actions: { addToOrder(item, quantity) { const searchIndex = this.tableOrders.findIndex((order) => order.id === item.id); if(searchIndex !== -1) { this.tableOrders[searchIndex].quantity += quantity } else { // 拷贝对象后再存入store,不修改外部原对象 this.tableOrders.push({ ...item, quantity: quantity }) } } } })
修改完成后,重置计数、重复添加同个商品的数量都可以正常触发视图更新。
内容的提问来源于stack exchange,提问作者Sasha
相关产品推荐
相关产品推荐

