Pinia Store :前端的 MVVM 解耦
Pinia Store :前端的 MVVM 解耦
在 Vue 开发的早期阶段,或者在编写简单的 .vue 文件时,我们习惯把 数据(State)、业务逻辑(Methods) 和 HTML 模板(View) 写在一起。这种“全家桶”式的写法虽然上手快,但随着业务复杂度增加,痛点也随之而来:UI 和业务逻辑紧紧捆绑在一个文件中。如果另一个页面也需要这份数据,或者想对这段复杂的逻辑进行单元测试,会发现寸步难行。
现状:耦合的代码 (The Problem)
1 | <!-- Component.vue --> |
痛点:这个 .vue 文件承担了太多的责任。它既要负责“长什么样”,又要负责“怎么运作”。
解决方案:引入 Pinia (The Solution)
是否有办法把数据的定义、计算和更新逻辑从 .vue 文件中彻底挪出来呢?
Vue 官方推荐的状态管理库 Pinia 正是为此而生。通过 Pinia,我们可以实现关注点分离:
- Store (Model/ViewModel):负责定义数据结构(
state)、计算属性(getters)和业务动作(actions)。它完全不关心数据是如何展示的(是列表?是图表?还是纯文本?)。 - Component (.vue):回归纯粹的 View。它只负责渲染数据和触发用户事件。
类比 WPF/MVVM
此时 .vue 只是数据的“订阅者”和“命令发送者”。如果熟悉 C# WPF 开发,这就是 MVVM 模式在前端的完美复刻:
- Store =
ViewModel- 持有数据属性:
IsLoading,ChartData - 持有命令/逻辑:
FetchCommand,CalculatedPrice
- 持有数据属性:
- Vue Component =
XAML(View)- 通过 Binding 绑定数据
- 通过 Event/Command 绑定行为
如何组织与定义
项目结构组织
在工程化项目中,我们通常会在 src 目录下建立独立的 stores 文件夹。建议遵循 Modular 的原则,按照业务领域划分 Store。
1 | frontend/ |
定义 Store (Setup Syntax)
在 src/stores/counter.ts 中:
1 | import { defineStore } from 'pinia' |
这一层是纯逻辑,不知 UI 为何物。 它可以被任何组件复用,甚至可以在 Node.js 环境下单独测试。
在组件中使用 (The View)
现在,.vue 文件变得异常清爽。组件只管“调用”,不管“如何实现”。
1 | <!-- Component.vue --> |