一、Store 是什么?
Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态 。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action,我们可以假设这些概念相当于组件中的 data、 computed 和 methods。
二、Pinia 是什么?
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
三、安装+全局引入
1、安装pinia
npm install pinia
2、创建 Pinia 实例
在项目入口文件(如 main.js
)中初始化并挂载 Pinia:
javascript
// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
注意:需确保所有 Store 的使用在 Pinia 实例挂载之后
四、定义Store-defineStore()
Store 是用 defineStore()
定义的,它的第一个参数要求是一个独一无二的名字:
javascript
import { defineStore } from 'pinia'
// 返回值最好以 `use` 开头且以 `Store` 结尾。
// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserStore = defineStore('user', {
// 其他配置...
})
**返回值(useUserStore):**最好以 `use` 开头且以 `Store` 结尾
第一个参数(user): 也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。
**第二个参数:**可【Setup函数】或【Option对象】
1、【Option 对象】------推荐使用
传入一个带有 state
、actions
与 getters
属性的 Option 对象
javascript
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
name: 'Eduardo'
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
简单理解:
state
是 store 的数据 (data
)
getters
是 store 的计算属性 (computed
)
actions
是方法 (methods
)优点:简单,容易使用
2、【Setup函数】
也可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。
javascript
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const name=ref("Eduardo")
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
在 Setup Store 中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
- 注意:必须 在 setup store 中返回 state****的所有属性 。
优点:更灵活可以在 store 内创建侦听器
可以依赖于全局提供的属性,比如路由。
任何应用层面提供的属性都可以在 store 中使用
inject()
访问,就像在组件中一样
五、基础示例
1、创建Store:
javascript
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return {
count: 0.
name: 'Eduardo',
isAdmin: true,
items: [],
hasChanged: true,
}
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++
},
},
})
return { count, increment }
})
2、使用Store --useCounterStore():
javascript
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.count++
// 自动补全! ✨
counter.$patch({ count: counter.count + 1 })
// 或使用 action 代替
counter.increment()
//从Store解构
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
<template>
<!-- 直接从 store 中访问 state -->
<div>Current Count: {{ counter.count }}</div>
</template>
store
是一个用 reactive
包装的对象,就像 setup
中的 props
一样,我们不能对它进行解构:
六、State
state 都是你的 store 的核心。在 Pinia 中,state 被定义为一个返回初始状态的函数。
1、定义
javascript
import { defineStore } from 'pinia'
const useUserStore = defineStore('user', {
// 为了完整类型推理,推荐使用箭头函数
state: () => {
return {
// 所有这些属性都将自动推断出它们的类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [],
hasChanged: true,
}
},
})
2、使用
html
<script setup>
import { useUserStore } from '@/stores/counter'
const store = useUserStore()
//访问
store.count++
//重置-将state重置为初始值
store.$reset()
//变更多个属性
store.$patch({
count: store.count + 1,
name: "aaa",
})
//另一种变更方式
store.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
</script>
注意:
使用Setup stores中,重置需要创建自己的$reset()方法,例如
javascript
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function $reset() {
count.value = 0
}
return { count, $reset }
})
七、Getter
1、定义
Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore()
中的 getters
属性来定义它们。推荐使用箭头函数 ,并且它将接收 state
作为第一个参数:
javascript
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
大多数时候,getter 仅依赖 state。不过,有时它们也可能会使用其他 getter(自行学习)
2、使用
html
<script setup>
import { useCounterStore } from './counterStore'
const store = useCounterStore()
</script>
<template>
<p>Double count is {{ store.doubleCount }}</p>
</template>
八、Action
1、定义
Action 相当于组件中的 method。它们可以通过 defineStore()
中的 actions
属性来定义
javascript
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
action 可通过 this
访问整个 store 实例
2、使用
Action 可以像函数或者通常意义上的方法一样被调用:
html
<script setup>
const store = useCounterStore()
// 将 action 作为 store 的方法进行调用
store.randomizeCounter()
</script>
<template>
<!-- 即使在模板中也可以 -->
<button @click="store.randomizeCounter()">Randomize</button>
</template>
其他用法:
访问其他store的action
订阅action------
store.$onAction()
九、配置状态持久化------persist
过这个设置,你可以指定哪些状态属性需要被保存到 localStorage
或 sessionStorage
中,从而在页面刷新或重新加载后仍然保持这些数据。
使用方法
-
安装插件:
npm install pinia-plugin-persistedstate
-
引入并使用插件: 在 Pinia 实例中添加插件:
javascript
import './assets/main.css'
import { createApp } from 'vue'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
import {createPinia} from "pinia";
import App from './App.vue'
import router from './router'
const store = createPinia()
store.use(piniaPluginPersistedstate);
createApp(App).use(store).use(router).mount('#app')
- 配置 Store 的持久化路径 : 在定义 store 时,通过
persist.paths
指定需要持久化的属性:
javascript
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
loginType: '',
clientId: '',
// 其他不需要持久化的状态...
}),
persist: {
paths: ['loginType', 'clientId'], // 只保存这两个属性
},
});
这样,只有 loginType
和 clientId
这两个属性会被自动同步到浏览器的存储中,在页面刷新后依然可用。
高级配置
除了 paths
,还可以进一步自定义持久化行为:
- storage :选择
localStorage
或sessionStorage
。
javascript
persist: {
storage: sessionStorage,
paths: ['loginType', 'clientId'],
}
- serializer:自定义数据的序列化与反序列化方式。
javascript
persist: {
serializer: {
serialize: (value) => JSON.stringify(value),
deserialize: (value) => JSON.parse(value),
},
paths: ['loginType', 'clientId'],
}
配置选项说明
- key: 存储数据的键名,默认为 store 的 id。
- storage : 数据存储位置,默认为
localStorage
,也可改为sessionStorage
。 - paths : 指定哪些状态路径需要持久化,如
['token']
。 - serializer: 自定义序列化和反序列化方法,支持加密等需求。
- beforeRestore 和 afterRestore: 分别在恢复数据前后触发的钩子函数。
详情可见Pinia官网:Pinia | The intuitive store for Vue.js
我只是学习路上记录了一下~