Vue.js 如何将IncomeList与OutputList的求和结果传递至WinTotal组件
Vue 跨组件求和值传递可落地实现
之前尝试传值失败的核心原因:props仅支持父组件向子组件单向传值,平级组件之间无法直接通过props互传,只要理清共同父级/全局状态的中转逻辑,两种方案都能快速跑通。
方案1:无额外依赖,通过共同父组件中转实现
适配三个组件为平级兄弟的常见结构(公共父页面下并列渲染IncomeList、OutputList、WinTotal),步骤如下:
- 在公共父组件中定义两个响应式变量,作为求和值的中转存储
// 公共父组件代码 import { ref } from 'vue' // 存储两个组件的求和结果 const totalIncome = ref(0) const totalOutput = ref(0) // 定义接收子组件上传数据的方法 const receiveIncomeSum = (val) => totalIncome.value = val const receiveOutputSum = (val) => totalOutput.value = val - 父组件模板中绑定自定义事件与传值逻辑
<template> <!-- 给两个列表组件绑定值回传的监听事件 --> <IncomeList @sum-update="receiveIncomeSum" /> <OutputList @sum-output-update="receiveOutputSum" /> <!-- 把中转存储的两个求和值传给WinTotal组件 --> <WinTotal :total-income="totalIncome" :total-output="totalOutput" /> </template> - 改造IncomeList、OutputList内部的求和方法,计算完成后主动把结果抛给父组件
// IncomeList 内部sumValue方法改造 const emit = defineEmits(['sumUpdate']) // 声明向外抛出的事件 const sumValue = (list) => { const sum = list.reduce((acc, item) => acc + item.amount, 0) // 计算完成后把结果传给父组件 emit('sumUpdate', sum) return sum } // OutputList 内部sumValueOutput方法改造 const outputEmit = defineEmits(['sumOutputUpdate']) const sumValueOutput = (list) => { const sum = list.reduce((acc, item) => acc + item.amount, 0) outputEmit('sumOutputUpdate', sum) return sum } - WinTotal组件内部正常接收props参数即可
const props = defineProps({ totalIncome: { type: Number, default: 0 }, totalOutput: { type: Number, default: 0 } }) // 直接基于传入的props计算最终汇总值 const netTotal = computed(() => props.totalIncome - props.totalOutput)
该方案常见踩坑点:只做了父组件向子组件的单向props传值,忘了让两个列表组件在计算完求和值后,通过
emit自定义事件把结果回传给共同父级,导致父组件存储的中转值永远是初始的0,最终传给WinTotal的也是无效值。
方案2:基于Vuex实现全局状态共享
适配项目已经集成Vuex、存在多页面共享财务汇总数据的场景,配置步骤如下:
- 在Vuex的对应模块state中定义汇总字段
// store/modules/finance.js state: () => ({ incomeSum: 0, outputSum: 0 }) - 定义对应mutation,用来同步最新的求和结果
mutations: { SET_INCOME_SUM(state, val) { state.incomeSum = val }, SET_OUTPUT_SUM(state, val) { state.outputSum = val } } - 改造两个列表组件的求和方法,计算完成后直接提交mutation更新全局状态
// IncomeList 内部sumValue方法改造 import { useStore } from 'vuex' const store = useStore() const sumValue = (list) => { const sum = list.reduce((acc, item) => acc + item.amount, 0) // 提交mutation更新全局存储的收入汇总值 store.commit('finance/SET_INCOME_SUM', sum) return sum } // OutputList 内部sumValueOutput方法同理,计算完成后提交`finance/SET_OUTPUT_SUM`即可 - WinTotal组件直接从全局store中取数,无需依赖组件层级传值
import { computed } from 'vue' import { useStore } from 'vuex' const store = useStore() const incomeSum = computed(() => store.state.finance.incomeSum) const outputSum = computed(() => store.state.finance.outputSum) const netTotal = computed(() => incomeSum.value - outputSum.value)
该方案常见踩坑点:
- Vuex模块开启了命名空间
namespaced: true,提交mutation时漏写模块前缀,导致找不到对应更新方法- WinTotal组件取store值时没有用
computed包裹,导致值更新后页面无响应- 求和方法仅在组件首次加载时触发一次,列表数据变更后没有重新执行求和逻辑,导致store中的值始终是初始计算的旧值
内容的提问来源于stack exchange,提问作者Volnick
相关产品推荐
相关产品推荐

