哈喽兄弟们,我是大布布将军!👋
上一期咱们聊了 Composition API 是如何把 Mixin 送进历史博物馆的。评论区就有小伙伴坐不住了:“将军,逻辑复用是爽了,那状态管理呢?我看着手里的 Vuex 4 代码,满屏的 mutations、actions、modules,还有那个让 TypeScript 抓狂的类型推导,我是不是该换个活法了?”
嘿,你问到点子上了!
如果说 Vuex 是一个等级森严、办事流程繁琐的老牌国企(改个数据还得层层审批),那 Pinia 就是一个扁平化管理、效率至上的互联网大厂(想改?直接改,别废话)。
今天,咱们就来扒一扒,这颗“小菠萝”(Pinia)到底凭什么篡位成功,成为了 Vue 3 官方推荐的“御用”状态管理库。
一、Vuex 的“劝退”时刻:你还在写 mutations 吗?
回想一下,在 Vuex 时代,我们想把一个计数器 count 加 1,需要经历什么流程?
- State: 定义
count。 - Mutation: 定义一个
INCREMENT方法(因为 Vuex 规定,只有 Mutation 能改 State,这叫“同步事务”)。 - Action: 如果是异步的,还得定义一个 Action,然后
commit那个 Mutation。 - Component: 在组件里
dispatchAction。
我就想加个 1 而已啊! 这流程走下来,感觉像是在填报销单,还得找三个领导签字。
Pinia 的回答:删繁就简
Pinia 也就是看不过去这一点,直接把 mutations 砍了。是的,你没听错,砍了!
在 Pinia 里,Action 既可以处理同步,也可以处理异步。想改数据?在 Action 里直接 this.count++,或者在组件里直接改,没人管你。
二、代码大PK:没有对比就没有伤害
光说不练假把式,咱们直接上代码,看看实现同一个“计数器”功能,两者差多少。
选手 A:Vuex 4(繁琐的老大哥)
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
// 必须要有 mutations 才能改 state
mutations: {
INCREMENT(state) {
state.count++
}
},
// 异步操作或者复杂逻辑放这里
actions: {
increment({ commit }) {
commit('INCREMENT') // !!! 这行代码我写了一万遍,真的累了
}
},
getters: {
doubleCount: (state) => state.count * 2
}
})
选手 B:Pinia(清爽的小菠萝)
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// state 必须是箭头函数(为了服务端渲染 SSR 安全)
state: () => ({
count: 0
}),
// actions 直接干活,没有 mutations 中间商赚差价
actions: {
increment() {
this.count++ // 👈 直接改!爽!
}
},
getters: {
doubleCount: (state) => state.count * 2
}
})
或者,你还可以用更激进的 Setup Store 写法(配合 Composition API,简直起飞):
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
看到区别了吗?没有 mutations,没有 commit,没有魔法字符串。 代码量直接减半,逻辑清晰度翻倍。
三、TypeScript 支持:Vuex 的噩梦 vs Pinia 的天堂
如果你在 Vuex 里用过 TypeScript,你一定经历过绝望。
为了让 this.$store.state 有类型提示,你需要写一堆 interface,甚至还要搞什么 ModuleTree,还得自己封装 useStore... 也就是俗称的“TS 体操”。写完配置,头发都掉了一把。
Pinia 呢?
它天生就是为了 TS 设计的。上面的 Pinia 代码写完,你在组件里调用:
counter. // 👈 这里一敲点,IDE 瞬间把 count, increment 全提示出来了
自动推导,零配置。 这种丝滑的感觉,就像夏天喝了一口冰镇可乐,通透!
四、架构之争:树形 vs 扁平化
Vuex 是单棵大树: 所有的模块都要挂载到一个 root store 下面,形成一个巨大的树形结构。 访问深层数据时:state.user.permissions.admin.level... 如果要做代码分割(Code Splitting),那简直是灾难。
Pinia 是模块化积木: 没有 root store!每个 Store 都是独立的。 你需要 UserStore?引入它。 你需要 CartStore?引入它。 它们之间互相引用也很简单。这不仅让代码逻辑解耦,还天然支持代码分割和按需加载,打包体积都变小了。
总结:这是时代的必然
Pinia 其实最初就是作为 Vuex 5 的实验性提案出现的,结果做着做着发现:“哎?这玩意儿比 Vuex 好用太多了!” 于是 Vue 官方直接把它扶正了。
Pinia 赢在哪?
- 极简: 抛弃
mutations,API 更符合直觉。 - TS 亲和: 类型推导极其强大,不用练“体操”。
- 轻量: 体积极小(约 1KB),且支持模块化打包。
所以,兄弟们,如果你还在犹豫要不要在 Vue 3 项目里用 Pinia,别犹豫了,上车吧! 把 Vuex 留在记忆里,把 Pinia 写进代码里。
互动时间: 你在从 Vuex 迁移到 Pinia 的过程中,有没有遇到什么“真香”时刻或者“坑”?或者你还在坚持用 Vuex?欢迎评论区对线!
下期预告: 既然 Vue 3 和 Pinia 都这么快了,那构建工具岂能拉胯?Vite 到底施了什么魔法,能比 Webpack 快那么多?是不是有了 Vite,Webpack 就要凉凉了?咱们下期接着聊!