Pinia
是一个全新的Vue
状态管理库,是Vuex
的代替者,尤雨溪强势推荐
Vue2
和 Vue3
都能支持Mutation
,只有 state
, getter
和 action
,简化状态管理库Vue3
的 Composition api
,让代码扁平化TypeScript
支持1.安装Pinia: npm i pinia
2.挂载Pinia
// main.js
import {createPinia} from "pinia";
const pinia = createPinia();
app.use(pinia);
3.使用defineStore
创建一个store
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
// 也可以定义为
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++
},
},
})
4.在组件中使用
<template>
<div>
<h1>{{counter.count}}</h1>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import { useCounterStore } from "../stores/counter";
const counter = useCounterStore();
onMounted(() => {
counter.count++;
// 带自动补全 ✨
counter.$patch({ count: counter.count + 1 });
// 或使用 action 代替
counter.increment();
});
</script>
Store 是使用 defineStore()
定义的,并且它需要一个唯一名称,作为第一个参数传递:
import { defineStore } from 'pinia'
// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main', {
// other options...
})
这个 name
,也称为 id
,是必要的,Pinia
使用它来将 store
连接到 devtools
。 将返回的函数命名为 use...
是跨可组合项的约定,以使其符合你的使用习惯。
store
是一个用reactive
包裹的对象,这意味着不需要在getter
之后写.value
,但是,就像setup
中的props
一样,我们不能对其进行解构。
为了从 Store
中提取属性同时保持其响应式,您需要使用storeToRefs()
。 它将为任何响应式属性创建 refs
。 当您仅使用 store 中的状态但不调用任何操作时,这很有用:
import { storeToRefs } from 'pinia'
export default defineComponent({
setup() {
const store = useStore()
// `name` 和 `doubleCount` 是响应式引用
// 这也会为插件添加的属性创建引用
// 但跳过任何 action 或 非响应式(不是 ref/reactive)的属性
const { name, doubleCount } = storeToRefs(store)
return {
name,
doubleCount
}
},
})
除了直接用 store.counter++
修改 store
,你还可以调用 $patch
方法。 它允许您使用部分“state”对象同时应用多个更改:
store.$patch({
counter: store.counter + 1,
name: 'Abalam',
})
$patch
方法也接受一个函数来批量修改集合内部分对象的情况:
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
您可以通过将其 $state
属性设置为新对象来替换 Store
的整个状态:
store.$state = { counter: 666, name: 'Paimon' }
可以通过 store
的 $subscribe()
方法查看状态及其变化,类似于 Vuex
的 subscribe
方法。 与常规的 watch()
相比,使用 $subscribe()
的优点是 subscriptions
只会在 patches
之后触发一次。
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 // 补丁对象传递给 to cartStore.$patch()
// 每当它发生变化时,将整个状态持久化到本地存储
localStorage.setItem('cart', JSON.stringify(state))
})
默认情况下,state subscriptions
绑定到添加它们的组件(如果 store
位于组件的 setup()
中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true }
作为第二个参数传递给 detach
当前组件的 state subscription
:
export default {
setup() {
const someStore = useSomeStore()
// 此订阅将在组件卸载后保留
someStore.$subscribe(callback, { detached: true })
// ...
},
}