Pinia 是 Vue 的存储库,允许您跨组件/页面共享状态。
npm i -S pinia
import { createPinia } from 'pinia'
const store = createPinia()
export default store
import { createApp } from 'vue'
import App from './App.vue'
import store from './store/index';
const app = createApp(App);
app.use(store).mount('#app')
Store 是一个保存状态和业务逻辑的实体,可以自由读取和写入,并通过导入后在 setup 中使用创建一个 store
//新建src/store/user.ts
import { defineStore } from 'pinia';
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '小白龙',
};
},
});
<template>
<div>{{ userStore.name }}</div>
</template>
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
</script>
state 也可以使用解构,但使用解构会使其失去响应式,使用 storeToRefs可以不失去响应式
<template>
<div>{{ name }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
const { name } = storeToRefs(userStore)
</script>
state 直接赋值给变量,会使其失去响应式,使用vue3的computed()可以不失去响应式
<template>
<div>{{ name }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
const name = computed(() => useUserStore.name)
</script>
userStore.name = '小龙龙'
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '小白龙',
age:18,
friendList: [
{ name: '浪里小白龙', age: 18 },
{ name: '浪里个浪小白龙', age: 20 },
]
}
},
actions() {
updateName(name: string) {
this.name = name
}
}
})
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
userStore.updateName('小龙龙')
</script>
$patch的方式是经过优化的,多条数据同时更新状态数据会加快修改速度,性能有很大的好处。
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
//方式一(浅层修改)
userStore.$patch({
name: '浪里' + userStore.name,
age: userStore.age + 2
});
//方式二(深层修改)
userStore.$patch(state => {
state.name = '浪里' + userStore.name;
state.age = userStore.age + 2;
state.friendList[0].name = '小萝莉'
});
</script>
可以通过调用store 上的方法将状态重置为初始状态
<script lang="ts" setup>
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
userStore.$reset()
</script>
通过 store.$subscribe() 的方法,该方法的第一个参数接受一个回调函数,该函数可以在 state 变化时触发
const subscribe = mainStore.$subscribe((mutation, state) => {
console.log(mutation)
console.log(state)
})
其中 state 是 mainStore 实例,而 mutation 打印如下
可以发现,打印结果的mutation对象主要包含三个属性
events : 是这次state改变的具体数据,包括改变前的值和改变后的值等等数据
storeId :是当前store的id
type:type表示这次变化是通过什么产生的,主要有三个分别是
store.$subscribe() 的方法的第二个参数options对象,是各种配置参数,包括
detached属性,其值是一个布尔值,默认是 false, 正常情况下,当 订阅所在的组件被卸载时,订阅将被停止删除,如果设置detached值为 true 时,即使所在组件被卸载,订阅依然可以生效。
其他属性主要还有 immediate、deep、flush 等等,和 vue3 watch的对应参数效果一样。
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '小白龙',
}
},
getters: {
formatName: (state) => {
return state.name + '0418';
},
},
})
userStore.formatName //小白龙0418
新建store/user.js文件
import { defineStore } from 'pinia'
const useUserStore = defineStore('user', {
state: () => {
return {
count: 0
}
},
getters: {
double() {
return this.count * 2
},
}
})
export default useUserStore
新建store/counter.js文件
import { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {
state: () => {
return {
name: 'ls',
age: 120,
}
},
})
export default useCounterStore
新建store/index.js
import useUserStore from './user'
import useCounterStore from './counter'
// 统一导出useStore方法
export default function useStore() {
return {
user: useUserStore(),
counter: useCounterStore(),
}
}
在组件中使用
<script setup>
import { storeToRefs } from 'pinia'
import useStore from './store'
const { counter } = useStore()
// 使用storeToRefs可以保证解构出来的数据也是响应式的
const { user, counter } = storeToRefs(counter)
</script>
ref 与 state 对应、computed 与 getters 对应、function 与 actions 对应。
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
/** 在 setup 外使用 */
export function useCounterStoreHook() {
return useCounterStore(store)
}
解决页面刷新,Pinia数据丢失
npm i -S pinia-plugin-persistedstate
// src/store/index.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(piniaPluginPersistedstate)
export default store
//src/store/user.ts
import { defineStore } from 'pinia';
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
name: '小白龙',
};
},
actions: {
updateName(name: string) {
this.name = name;
},
},
getters: {
formatName: (state) => {
return state.name + '0418';
},
},
// 开启数据缓存
persist: true,
});
数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key你也可以在 strategies 里自定义 key 值,并将存放位置由 sessionStorage 改为 localStorage。
// 开启数据缓存
persist: {
storage: sessionStorage,
paths: ['someState'],
},
默认所有 state 都会进行缓存,你可以通过 paths 指定要持久化的字段,其他的则不会进行持久化。
state: () => {
return {
name: '小白龙',
age: 18,
gender: '男'
}
},
persist: {
storage: sessionStorage,
paths: ['someState'],
},