vue3重点2-pinia
2、pinia——全局状态管理
Vuex 是 Vue2 时代的强制规范,设计偏笨重、冗余;
Pinia 是 Vue3 专为组合式 API、TS、轻量化设计,功能全覆盖、写法更简单、无冗余,完全平替 Vuex,还更好用。
vuex缺点
-
强制划分
state / getters / mutations / actions太繁琐只能在 mutations 改 state
异步逻辑必须放 actions
改个简单数据,要走:组件 dispatch → actions → commit → mutations 改 state
修改一个state要通过太多嵌套的代码层级
-
必须用
this.$store或 映射函数Vue2 选项式还能凑合,到了 Vue3
<script setup>:-
没有
this -
要用
useStore还得引入辅助函数 -
mapState、mapGetters、mapActions写法啰嗦、解构麻烦
-
-
模块嵌套 modules 层级太深
大型项目拆模块后:
store.modules.user.info.name
层级嵌套深,取值麻烦,命名容易冲突。
-
TypeScript 支持差
Vuex 类型推导很弱,需要额外写大量类型声明,TS 体验极差。
pinia的解决方案
1、Pinia 只有三个核心:
state / getters / actions——直接去除了mutations来简化结构
-
同步、异步修改 state 全都直接写在 actions 里
-
不需要 commit、不需要 mutations
-
想改数据:直接改 或 调用 action 就行
Vuex 繁琐流程
组件 → dispatch (action) → commit (mutation) → 修改 state
Pinia 极简流程
组件 → 直接改 state 或 调用 action → 修改 state
2、天然适配 Vue3 <script setup>,没有 this 也能用
<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 直接用数据、直接调方法
userStore.name
userStore.login()
</script>
3、扁平化模块,不再嵌套
Pinia 每个仓库都是独立扁平的:
-
不用嵌套 modules
-
每个
defineStore独立命名、互不干扰 -
引用哪个就导入哪个,结构清晰
4、原生顶级 TS 支持
自动类型推导
state、getters、actions 全部自带类型提示
不用额外定义复杂接口,大型项目类型极其友好
pinia实例
1、main.js全局注册
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
// 创建pinia实例
const pinia = createPinia()
createApp(App).use(pinia).mount('#app')
2、新建仓库
import { defineStore } from 'pinia'
// 定义仓库:唯一id 为 counter
export const useCounterStore = defineStore('counter', {
// 1. 全局状态(相当于data)
state: () => ({
count: 0,
username: '张三'
}),
// 2. 计算属性(相当于computed)
getters: {
doubleCount: (state) => state.count * 2
},
// 3. 全局方法:同步 + 异步(相当于methods)
actions: {
// 同步修改
increment() {
// 这里可以用this,指向当前store
this.count++
},
setName(name) {
this.username = name
},
// 异步方法(模拟接口请求)
async asyncChangeCount() {
// 模拟接口延迟
await new Promise(resolve => setTimeout(resolve, 1000))
this.count += 10
}
}
})
3、组件中使用
<template>
<div>
<h3>原始值:{{ counterStore.count }}</h3>
<h3>计算属性双倍值:{{ counterStore.doubleCount }}</h3>
<h3>用户名:{{ counterStore.username }}</h3>
<!-- 1. 直接改数据 -->
<button @click="counterStore.count++">直接+1</button>
<!-- 2. 调用pinia同步方法 -->
<button @click="counterStore.increment">调用action+1</button>
<button @click="counterStore.setName('李四')">修改名字</button>
<!-- 3. 调用异步方法 -->
<button @click="counterStore.asyncChangeCount">异步+10</button>
</div>
</template>
<script setup>
// 引入仓库
import { useCounterStore } from '@/stores/counter'
// 获取仓库实例,直接就能用
const counterStore = useCounterStore()
</script>更多推荐
所有评论(0)