Pinia是Vue的储存库,允许跨组件/页面共享状态
yarn add pinia
# 或者使用 npm
npm install pinia
import { createApp } from 'vue';
import App from './App.vue';
// 创建pinia
import { createPinia } from 'pinia';
const pinia = createPinia();
const app = createApp(App);
app.use(pinia).mount('#app')
import { defineStore } from 'pinia'
// useStore 也可以是 useUser useXxxxStore 之类的任何东西
// 第一个参数是应用程序中 store的唯一id
// 第二个参数为一个对象,提供 state getters actions
const useStore = defineStore('main', {
state:() => {
return {
count: 1
}
},
getters: {},
actions: {}
})
export default useStore
这个name,也称为id,是必要的,Pinia使用它来将store连接到 devtools。将返回的函数命名为 use… 是跨可组合项的约定,以使其符合你的使用习惯
<template>
<h1>{{ store.count }}</h1>
</template>
<script>
import { defineComponent } from "vue";
import { useStore } from '@/stores/index'
export default defineComponent({
setup() {
const store = useStore()
return {
store
}
}
})
</script>
注意:如果想要解构store赋值是不可行的,因为它会破坏响应式
setup() {
const store = useStore()
// ❌ 这不起作用,因为它会破坏响应式
const { count } = store
return {
count, // 一直会是 1
// 这将是响应式的
count: computed(() => store.count),
}
},
为了从 store中提取属性的同时保持其想应收,需要用到 storeToRefs()。它将为任何响应式属性创建refs。
import { storeToRefs } from "pinia";
setup(){
const store = useStore()
const { count } = storeToRefs(store)
return {
count
}
}
getters 完全等同于 store 状态的计算值
export const useStore = defineStore('main', {
state: () => {
return {
count: 1,
}
},
getters: {
// 自动将返回类型推断为数字
doubleCount(state) {
return state.count* 2
},
// 设置了返回类型
doublePlusOne(): number {
return this.count* 2 + 1
},
},
})
// 在组件中使用
<template>
<p>Double count is {{ store.count }}</p>
<p>DoublePlusOne count is {{ store.count }}</p>
</template>
<script>
setup() {
const store = useStore()
return {
store
}
}
</script>
getters 只是幕后的 computed 属性,因此无法向它们传递任何参数。但是,你可以从 getters 返回一个函数接收任何参数
export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
// 在组件中使用
<script>
export default {
setup() {
const store = useStore()
return {
getUserById: store.getUserById
}
},
}
</script>
<template>
<p>User 2: {{ getUserById(2) }}</p>
</template>
访问其他 store 的 getter
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => {
return {
localData: ...
}
},
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
不管是同步还是异步的代码,都可以在 actions 中完成。actions 相当于组件中的 methods
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCount() {
this.count = Math.round(100 * Math.random())
},
incrementAsync() {
setTimeout(() => {
this.count++
}, 1000)
}
},
})
在组件中使用
<h1>数量---{{ store.count }}</h1>
<button @click="store.increment">加1</button>
<button @click="store.randomizeCount">随机</button>
<button @click="store.incrementAsync">异步加1</button>
setup() {
const store = useStore()
return {
store
}
},
在项目中,不可能把多个模块的数据放在一个store中,一般都是一个模块对应一个store,再通过一个跟store进行整合
// 新建store/user.js
import { defineStore } from 'pinia'
const useUserStore = defineStore('user', {
state: () => {
return {
name: 'zs',
age: 18,
}
},
})
export default useUserStore
//新建store/app.js
import { defineStore } from 'pinia'
const useAppStore = defineStore('app', {
state: () => {
return {
roles: []
}
},
})
export default useAppStore
// 在store/index.js 中
import useUserStore from './user'
import useAppStorefrom './app'
// 统一导出useStore方法
export default function useStore() {
return {
user: useUserStore(),
counter: useAppStorefrom (),
}
}
// 在组件中使用
<script>
import useStore from "@/store/index";
setup() {
const { app, user } = useStore();
const { name, age } = storeToRefs(user)
}
</script>
yarn add pinia-plugin-persistedstate
or
npm i pinia-plugin-persistedstate
import { createApp } from 'vue';
import App from './App.vue';
// 创建pinia
import { createPinia } from 'pinia';
// 引入 pinia插件-数据持久化
import PiniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const pinia = createPinia();
pinia.use(PiniaPluginPersistedstate)
const app = createApp(App);
app.use(pinia).mount('#app');
import { defineStore } from 'pinia'
export const useStore = defineStore('store', {
state: () => {
return {
someState: 'hello pinia',
}
},
persist: true,
})
import { defineStore } from 'pinia'
export const useStore = defineStore('store', {
state: () => {
return {
someState: 'hello pinia',
}
},
persist: {
key: 'someState', // 作为存储的默认秘钥,存储中的键名称
storage: sessionStorage, // 默认为localStorage
paths: ['someState'], // 部分保持状态的点符号路径数组。[]意味着没有状态被持久化,undefined或者null意味着整个状态被持久化
},
})