如何正确使用Vuex Store多模块实现收支余额计算与列表展示
方案选型建议
两种实现方式没有绝对的优劣,按照你的业务场景选就行:
- 如果总余额、合并收支列表的逻辑只在当前这一个组件里用,直接在组件内引入两个模块的getter计算就行,不需要额外修改store代码,更轻量
- 如果后续有多个组件都需要用到总余额、合并收支数据,就把计算逻辑放到根store的getter里统一维护,避免多组件重复写计算逻辑
具体实现方式
方式1:组件内直接引入两个模块的getter完成计算
这是你当前场景最快捷的实现方式,只需要修改你的余额组件代码即可:
<template> <div> <!-- 总余额 --> <div class="total-value" :style="balanceColor"> Balance: {{ totalBalance }} </div> <!-- 合并的收支列表 --> <div class="record-list"> <div v-for="record in mergedRecordList" :key="record.id"> <span>{{ record.type }}</span> <span>{{ record.value }}</span> <span>{{ record.comment }}</span> </div> </div> </div> </template> <script> import {mapGetters} from 'vuex'; export default { name: 'TBalance', computed: { balanceColor: function() { return { color: this.totalBalance === 0 ? 'black' : this.totalBalance > 0 ? 'green' : 'red' } }, // 计算总余额 totalBalance() { const incomeTotal = Object.values(this.incomeList).reduce((acc, item) => acc + item.value, 0) const outcomeTotal = Object.values(this.outcomeList).reduce((acc, item) => acc + item.value, 0) return incomeTotal + outcomeTotal }, // 合并收支列表,如果需要按时间排序可以在这里加sort逻辑 mergedRecordList() { return [...Object.values(this.incomeList), ...Object.values(this.outcomeList)] }, // 同时引入两个命名空间模块的getter ...mapGetters("income", ["incomeList"]), ...mapGetters("outcome", ["outcomeList"]), }, } </script>
方式2:根store统一封装计算逻辑
如果多组件复用这些数据,就修改根store的index.js,新增全局getter:
import Vue from "vue"; import Vuex from "vuex"; import income from "./modules/income"; import outcome from "./modules/outcome"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, mutations: {}, actions: {}, getters: { // 总余额 totalBalance: (state, getters) => { const incomeTotal = Object.values(getters['income/incomeList']).reduce((acc, item) => acc + item.value, 0) const outcomeTotal = Object.values(getters['outcome/outcomeList']).reduce((acc, item) => acc + item.value, 0) return incomeTotal + outcomeTotal }, // 合并后的收支列表 mergedRecordList: (state, getters) => { return [...Object.values(getters['income/incomeList']), ...Object.values(getters['outcome/outcomeList'])] } }, modules: { income, outcome, }, });
之后组件直接从根getter取数据即可:
<script> import {mapGetters} from 'vuex'; export default { name: 'TBalance', computed: { balanceColor: function() { return { color: this.totalBalance === 0 ? 'black' : this.totalBalance > 0 ? 'green' : 'red' } }, ...mapGetters(["totalBalance", "mergedRecordList"]), }, } </script>
多Vuex模块在组件内使用的核心逻辑
因为你给两个模块都加了namespaced: true的命名空间配置,所以不管是mapGetters、mapState还是mapActions、mapMutations,只要第一个参数传入对应模块的命名空间名称,就可以引入对应模块的方法/状态,一个组件可以同时引入任意多个模块的资源。
内容的提问来源于stack exchange,提问作者1 2
相关产品推荐
相关产品推荐

