用完 Pinia,最后我自己掏出一套组合式 API 封装后,项目变清爽了、调试变简单了、开发变自由了。
Pinia 确实"像 Vuex 的现代替代品",但它仍然是一种「状态管理框架」,一旦项目复杂,它就成了"另一个 Vuex"。
组合式 API +
ref()+ 封装逻辑函数,其实就是你早就拥有的"更强 store"。
这是我最早喜欢 Pinia 的理由。你看这写法:
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
info: null,
}),
actions: {
setToken(token: string) {
this.token = token
},
},
})
是不是熟悉的感觉?既有 state,又有 actions,还能在组件里这样用:
const userStore = useUserStore()
userStore.setToken('abc')
但你写着写着,问题就来了。
来个真实案例: 登录成功后,要做三件事:
你是不是要这样写?
actions: {
async login(payload) {
const res = await loginApi(payload)
this.token = res.token
const userInfo = await fetchUserInfo()
this.info = userInfo
if (userInfo.isNew) {
// 在 store 里开弹窗?
// 还是 emit 事件?
// 还是从组件层判断?
}
}
}
你会发现:store 被耦合了 UI 行为。
你只想"登录",结果 store 里塞了一堆 UI 流程代码。 最后它变成了另一个"小 app.vue"。
Pinia 多模块管理要这样:
// user.ts
export const useUserStore = defineStore(...)
// cart.ts
export const useCartStore = defineStore(...)
// 然后全局注册、统一引入
看似干净,但本质还是 Vuex 那套模块思路,你想拆模块,要考虑:
但你换成组合式 API 呢?
// user.ts
export const useUser = () => {
const token = ref('')
const info = ref(null)
const setToken = (t: string) => token.value = t
return {
token, info, setToken
}
}
是不是就和普通 setup() 一样?用的时候直接:
const user = useUser()
user.setToken('abc')
逻辑拆分天然用文件系统组织,而不是人为"store 注册"绑定。
你以为写了:
state: () => ({
list: [],
count: 0
})
就响应式了?其实不是。
当你写:
this.list.push(123)
你有没有遇到页面没更新 的情况?因为不是用 this.list = [...this.list, 123]。
这时你得问自己:为什么我要去想"哪种操作才是响应式"?
组合式 API 根本不用想,直接:
const list = ref<number[]>([])
list.value.push(123) // 100% 响应式
还支持解构、传递、深度操作,不用 this,不用猜。
你可以像这样封一个 user.ts 模块:
// user.ts
import { ref } from 'vue'
const token = ref('')
const info = ref(null)
const setToken = (t: string) => token.value = t
const setInfo = (i: any) => info.value = i
exportfunctionuseUser() {
return {
token,
info,
setToken,
setInfo,
}
}
用的时候:
import { useUser } from '@/composables/user'
const user = useUser()
user.setToken('abc')
要是你怕每次都用一个新实例,也可以加缓存:
let instance: ReturnType<typeof createUser> | null = null
function createUser() {
const token = ref('')
...
return { token, ... }
}
export const useUser = () => {
if (!instance) instance = createUser()
return instance
}
这不就是你熟悉的 useXxxStore()?
Pinia 并不是没价值,它在以下场景更适用:
如果你有几十个状态模块、多人维护、需要强类型约束和统一 DevTools,那 Pinia 是更稳的方案。
用组合式 API 代替 Pinia,是一个完全自然的进化。
你会得到:更简单的状态定义, 更自由的逻辑组合, 更少的心智负担, 更轻的项目依赖(减少打包体积)
Pinia 有它的价值的,但不是每个 Vue 项目都需要它。
Vue 3 最大的价值,就是组合式 API 足够强,已经能当 Store 了。
所以在未来,我倾向这样的架构:
ref() 封装逻辑模块你们怎么看🙂
🔥号外~号外~
最近我们推出了大厂的一手面经模块,都是刚面完的小伙伴们热乎乎分享的:
这些面经都是花了不少心思整理的,比网上那些过时的八股文靠谱多了。
有需要的小伙伴可以点击这里👉前端面试题宝典(打开小程序,首页即可直接领取【大厂真实面经】),也可直接联系小助理咨询。
毕竟信息差就是竞争力,早点了解面试套路,早点拿到心仪offer!
有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。