在之前的Vue2版本中,官方的状态管理组件为Vuex;而Vue3的官方状态管理组件变更为了Pinia。
Vue3中有响应式对象,使用ref或reactive创建的就是响应式对象。但ref和reactive创建的对象一般是组件级别的,即当前组件(或页面)被销毁或不再显示,相应的数据也就全部销毁,无法保留。
如果需要多个组件(页面)共享数据,即全局状态,则需要使用Pinia。
npm install pinia --save
在main.ts中加上以下代码:
...
import { createPinia } from 'pinia';
...
const pinia = createPinia();
const app = createApp(App);
...
app.use(pinia);
...
一般在/src/stores
目录创建stroe。
// appStateStore.ts
export const useAppStateStore = defineStore('ujcmsAppStateStore', {
state: () => ({
sidebar: true,
messageBoxDisplay: false,
loginBoxDisplay: false,
}),
actions: {
setSidebar(sidebar: boolean) {
this.sidebar = sidebar;
},
closeSidebar() {
this.sidebar = false;
},
toggleSidebar() {
this.sidebar = !this.sidebar;
},
setMessageBoxDisplay(messageBoxDisplay: boolean) {
this.messageBoxDisplay = messageBoxDisplay;
},
setLoginBoxDisplay(loginBoxDisplay: boolean) {
this.loginBoxDisplay = loginBoxDisplay;
},
},
});
使用store
<script setup>
import { useAppStateStore } from '@/stores/appStateStore';
const store = useAppStateStore();
</script>
state即是状态。定义和使用都非常简单。直接拿来用即可,而且可以直接修改值。
export const useStore = defineStore('storeId', {
state: () => ({
count: 0,
}),
})
const store = useStore()
store.count++
getter相当于组件的computed
。
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
<script setup>
import { useCounterStore } from './counterStore'
const store = useCounterStore()
</script>
<template>
<p>Double count is {{ store.doubleCount }}</p>
</template>
actions可以定义一些方法,甚至是异步方法。相当于组件的methods
。
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
// since we rely on `this`, we cannot use an arrow function
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
<script setup>
const store = useCounterStore()
// call the action as a method of the store
store.randomizeCounter()
</script>
<template>
<!-- Even on the template -->
<button @click="store.randomizeCounter()">Randomize</button>
</template>
需要注意的是,Pinia虽然是全局共享的状态,但是一旦页面刷新,所有的数据将全部清除。
如果希望数据在页面刷新之后,依然保持原来的状态,则需要将数据持久化到sessionStorage里面;而如果希望数据在管理浏览器后,再次打开,依然保持原来状态,则需要将数据持久化到localStroage里面。
这两种情况都可以很容易的通过pinia-plugin-persistedstate
插件实现。
安装:
npm install pinia-plugin-persistedstate --save
创建。在main.ts中加上以下代码:
...
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
...
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
const app = createApp(App);
app.use(pinia);
...
定义:
export const useAppStateStore = defineStore('ujcmsAppStateStore', {
state: () => ({
sidebar: true,
messageBoxDisplay: false,
loginBoxDisplay: false,
}),
actions: {
...
},
persist: {
// 指定需要持久化的属性。默认持久化所有属性。
paths: ['sidebar'],
// 指定持久化的方式。默认localStorage。
storage: sessionStorage,
},
});