总价与总数量必须定义为Pinia getters:totalItems用reduce累加quantity,totalPrice先转整数运算再还原,确保精度与缓存;它们响应式自动更新、跨组件复用、避免methods重复执行和computed局部局限。

总价与总数量的 getter 定义方式
在 Pinia 中,购物车的总价和总数量应定义为 getters,而非普通 state 或 methods。它们基于 cartItems 数组实时计算,自动响应商品增删、数量变更等操作,且具备缓存机制,避免重复遍历。
典型写法如下(以 src/stores/cart.js 为例):
-
总数量:累加所有商品的
quantity字段 -
总价:对每项执行
price × quantity,再求和;推荐转为“分”整数运算防浮点误差
示例代码:
getters: {
totalItems: (state) => state.cartItems.reduce((sum, item) => sum + item.quantity, 0),
totalPrice: (state) => {
const totalCents = state.cartItems.reduce(
(sum, item) => sum + Math.round(item.price * 100) * item.quantity,
0
);
return (totalCents / 100).toFixed(2);
}
}为什么必须用 getters 而不是 computed 或 methods
组件内 computed 只在当前组件生效,无法被其他页面或模块复用;methods 每次调用都重新执行,无缓存,性能差且易遗漏更新触发。
而 Pinia 的 getters 是全局响应式派生状态:
- 任意组件通过
cartStore.totalPrice访问,值随 cartItems 变化自动更新 - 同一 getter 在多个地方使用,只计算一次,后续读取直接返回缓存结果
- 支持跨组件、跨路由共享逻辑,比如结算页和顶部购物车徽章共用同一总价
带选中状态的进阶计算
实际业务中常需区分“全部商品”和“已勾选商品”的统计。这时可扩展 getter,结合 checked 字段过滤:
-
选中商品总数量:
selectedItemsCount: (state) => state.cartItems.filter(i => i.checked).reduce((sum, i) => sum + i.quantity, 0) -
选中商品总价:
selectedTotalPrice: (state) => state.cartItems.filter(i => i.checked).reduce((sum, i) => sum + i.price * i.quantity, 0).toFixed(2)
注意:若价格含小数,仍建议统一转整数运算,避免 0.1 + 0.2 类精度问题影响最终显示。
在组件中安全使用 getter 值
直接解构 getter 会丢失响应性,正确做法是:
- 在
setup()中保持对 store 实例的引用,如const cart = useCartStore() - 模板中写
{{ cart.totalPrice }},不要写{{ totalPrice }}(未声明) - 如需在 script 中频繁访问,可用
storeToRefs(cart)解构 state,但 getter 仍建议直接调用,因其本身已是响应式计算函数


















