简介
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态,由 Vue.js团队成员开发。
vuex对比
- pinia的模块,不需要嵌套,模块之间可以互相引用,让代码组织更灵活
- 搭配 TypeScript 一起使用时有非常可靠的类型推断支持。
- 提供了一不仅个更简单的 API,也提供了符合组合式 API 风格的 API
安装
yarn add pinia
# 或者使用 npm
npm install pinia
完整实例
首先需要在main.js引入
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
定义状态Store
在深入研究核心概念之前,我们得知道 Store 是用 defineStore()
定义的,它的第一个参数要求是一个独一无二的名字:
import { defineStore } from 'pinia'
// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useStore = defineStore('main', {
// 其他配置...
})
这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use... 是一个符合组合式函数风格的约定。
defineStore()
的第二个参数可接受两类值:Setup 函数或 Option 对象。
TypeScript
你并不需要做太多努力就能使你的 state 兼容 TS。 Pinia 会自动推断出你的 state 的类型,但在一些情况下,你得用一些方法来帮它一把。
const useStore = defineStore('storeId', {
state: () => {
return {
// 用于初始化空列表
userList: [] as UserInfo[],
// 用于尚未加载的数据
user: null as UserInfo | null,
}
},
})
interface UserInfo {
name: string
age: number
}
访问 state
默认情况下,你可以通过 store
实例访问 state,直接对其进行读写。
const store = useStore()
store.count++
重置 state
你可以通过调用 store 的 $reset()
方法将 state 重置为初始值。
const store = useStore()
store.$reset()
变更 state
除了用 store.count++
直接改变 store,你还可以调用 $patch
方法。它允许你用一个 state
的补丁对象在同一时间更改多个属性
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
你也可以通过变更 pinia
实例的 state
来设置整个应用的初始 state。这常用于 SSR 中的激活过程。
pinia.state.value = {}
订阅 state
类似于 Vuex 的 subscribe 方法,你可以通过 store 的 $subscribe()
方法侦听 state 及其变化。比起普通的 watch()
,使用 $subscribe()
的好处是 subscriptions 在 patch 后只触发一次(例如,当使用上面的函数版本时)。
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 和 cartStore.$id 一样
mutation.storeId // 'cart'
// 只有 mutation.type === 'patch object'的情况下才可用
mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})
默认情况下,state subscription 会被绑定到添加它们的组件上(如果 store 在组件的 setup()
里面)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 { detached: true }
作为第二个参数,以将 state subscription 从当前组件中分离:
export default {
setup() {
const someStore = useSomeStore()
// 在组件被卸载后,该订阅依旧会被保留。
someStore.$subscribe(callback, { detached: true })
// ...
},
}
TIP
你可以在 pinia
实例上侦听整个 state。
watch(
pinia.state,
(state) => {
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)