Zustand和Pinia的对比(谁更好用)
先给结论:没有绝对更好,只看你用什么框架、项目规模、开发需求;
Vue项目:无脑pinia(官方原生、生态、调试全拉满)
React项目:Zustand几乎全方位吊打旧方案,比Pinia更适配React
两者框架互不通,Pinia是Vue专属,Zustand跨框架(React、vue、原生JS都能用)
1、基础信息
| Zustand | Pinia | |
| 所属框架 | 跨框架(react首选、vue、原生js通用) | vue专属 |
| 包体积 | 极小,~1.2kb | ~3kb |
| API极简度 | 极致极简,无Provider,无Reducer,无Mutation | 简洁,比vuex简单,但概念更多(state、getter、action) |
| ts类型 | 原生完美类型推导,几乎不用手动写类型 | 优秀,vue生态TS友好 |
| 更新方式 | set()直接该状态,写法极短 | 直接修改state,action封装,vue响应式原生 |
| 调试工具 | 支持devTools,够用 | Vue DevTools深度集成,调试体验顶级 |
| 模块化 | 多store原生,天然拆分,非常灵活 | 模块化完善,官方规范模块拆分 |
| 中间件 | 极强(持久化,中间件,选择器,钱比较内置) | 内置基础能力,持久化需插件,生态插件丰富 |
| 学习成本 | 极低,10分钟上手 | 低,vue开发者零成本(从vuex迁移) |
2、具体使用
Zustand
一、安装
npm install zustand #持久化插件(token存在localStorage,刷新不丢失必装) npm install zustand-persist二、store文件封装 src/store/userStore.ts
import {creact} from "zustand"; import {persist} from "zustand-persist"; //1.定义store数据类型 interface UserState{ token:string userInfo:{ username:string userId:number } //方法 //设置token setToken:(token:string)=>void //设置用户信息 setUserInfo:(info:UserState['userInfo'])=>void //退出登录:清空所有数据 logout:()=>void } //2.zustand封装+持久化自动存储 export const useUserStore=create<UserState>()( persist( (set)=>({ token:'', userInfo:null, //设置token setToken:(token)=>{ set({token}) }, //设置用户信息 setUserInfo:(userInfo)=>{ set({userInfo}) }, //退出登录-一键清空 logout:()=>{ set({ token:"", userInfo:null }) } }), { //持久化配置 key:'user_store',//localstorage key名字 storage:localStorage,//存储位置 }, ) )三、页面存储
import { useUserStore } from '@/store/userStore' function LoginPage() { // 解构获取数据和方法 const { token, userInfo, setToken, setUserInfo, logout } = useUserStore() // 模拟登录接口请求成功后 const handleLogin = async () => { // 假设接口返回 const res = { token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', user: { userId: 1001, username: '前端用户' } } // 存入全局状态 + 自动持久化到本地 setToken(res.token) setUserInfo(res.user) } return ( <div> <div>当前token:{token}</div> <button onClick={handleLogin}>模拟登录</button> <button onClick={logout}>退出登录</button> </div> ) } export default LoginPage四、取出调用
重点知识点:useUserStore.getState()非 React 组件、非 hooks 环境万能调用,axios、工具函数里通用
// src/utils/request.ts axios封装 import axios from 'axios' import { useUserStore } from '@/store/userStore' const service = axios.create({ baseURL: import.meta.env.VITE_BASE_URL }) // 请求拦截器 携带token service.interceptors.request.use((config) => { // 直接调用获取,无需hooks,无需组件内 const token = useUserStore.getState().token if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) export default servicePinia
一、安装
npm install pinia二、封装
import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ token: '', userInfo: null }), actions: { setToken(token) { this.token = token }, setUserInfo(info) { this.userInfo = info }, logout() { this.token = '' this.userInfo = null } }, persist: true })三、存储
const functionSubmit = (res) => { if (res.data.code === 200 && res.data.status) { let token= res.data.data.token;//根据后端返回的格式自定义 let userInfo= res.data.data.userInfo; //重要是这两个 userStore.setToken(questTicket); userStore.setUserInfo(userInfo); } };四、使用
import { useUserStore } from "@/stores/index.js"; // 确保路径正确 //使用 const userStore = useUserStore();两者对比总结
- 代码量:Zustand 略少一点点,但差距不大
- 上手难度:Zustand 概念更少,只有
state + set修改,没有 mutation、没有 getter - 跨组件 / 非组件调用
- Pinia:
useUserStore().xxx - Zustand:组件内 hooks,非组件
getState()非常顺手
- Pinia:
- 框架归属
- Pinia = 只属于 Vue
- Zustand = 只属于 React 生态首选千万不要在 Vue 用 Zustand,也不要在 React 硬用 Pinia
