Pinia
是 Vue.js 的轻量级状态管理库,最近很受欢迎。它的成功可以归功于其管理存储数据的独特功能(可扩展性、存储模块组织、状态变化分组、多存储创建等)
2021.11.24 Pinia 正式成为 vuejs 的一员,尤雨溪当天在 Twitter 上宣布:Pinia 正式成为 vuejs 官方的状态库,意味着 Pinia 就是 Vuex 5
官方解答
yarn add pinia
# or with npm
npm install pinia
创建一个 pinia(根存储)并将其传递给应用程序:
import { createPinia } from 'pinia'
app.use(createPinia())
创建一个 Store:
stores/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', { // 第一个参数必须是唯一的名称
state: () => ({ name: '张三', age: 18 , arr: [] }}
})
使用 Store:
<template>
<p>{{ userStore.name }}</p>
<p>{{ age }}</p>
</template>
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'
export default {
setup() {
const userStore = useUserStore()
const { name, age } = storeToRefs(store) // 解构写法
return {
userStore,
name,
age
}
}
}
你甚至可以使用一个函数(类似于一个组件setup())来为更高级的用例定义一个 Store:
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态:
const store = useStore()
store.counter++
除了直接用 store.counter++
, state 它允许您对部分对象同时应用多个更改:
userStore.$patch((state) => {
state.arr.push({ name: 'shoes', quantity: 1 })
state.name = '李四'
})
$state您可以通过将 store 的属性设置为新对象来替换 store 的整个状态:
const store = useStore()
store.$state = { counter: 666, name: 'Paimon' }
您可以通过调用store 上的方法将状态重置为其初始值:$reset()
const store = useStore()
store.$reset()
大多数时候,getter 只会依赖状态,但是,他们可能需要使用其他 getter。因此,我们可以在定义常规函数时访问整个store 实例,但需要定义返回类型的类型(在 TypeScript 中)
export const useStore = defineStore('main', {
state: () => ({ counter: 0 }),
getters: {
// doubleCount: (state) => state.counter * 2, // 类型被自动推断出来,因为我们没有使用' this '
doublePlusOne(): number { // 整个store的自动补全和类型设置 ✨
return this.counter * 2 + 1
}
}
})
然后你可以直接在 store 实例上访问 getter:
Pinia 没有 Mutations
,统一在 actions 中操作 state,通过this.xx 访问相应状态
虽然可以直接操作 Store,但还是推荐在 actions 中操作,保证状态不被意外改变
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`Welcome back ${this.userData.name}!`)
} catch (error) {
showTooltip(error)
// let the form component display the error
return error
}
}
}
你也可以完全自由地设置你想要的任何参数并返回任何东西。调用动作时像方法一样被调用,一切都会自动推断!
import { createRouter } from 'vue-router'
const router = createRouter({
// ...
})
// ❌ 根据导入的顺序,此操作将失败
const store = useStore()
router.beforeEach((to, from, next) => {
// 我们这里想用store
if (store.isLoggedIn) next()
else next('/login')
})
router.beforeEach((to) => {
// ✅ 这将工作,因为路由器开始它的导航之后
// 路由器已经安装,pinia也会安装
const store = useStore()
if (to.meta.requiresAuth && !store.isLoggedIn) return '/login'
})