一、简介
Pinia
是 Vue
的专属状态管理库,它允许你跨组件或页面共享状态。它跟 Vuex
有一定的相似度,但还是有很大的区别。
愿意看这篇博客的人,想必已经看过了官方文档,官方文档很详细,包含各种使用情景和理论,因此本文不说理论,只说具体的使用方法,想深入研究的建议去看官方文档,本文适合拿来即用。
Pinia 官方文档
二、使用方法
1. 安装
yarn add pinia
# 或者使用 npm
npm install pinia
2. 引入
main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
createApp(App).use(pinia).mount('#app') // vue3 的简写语法
不熟悉vue3简写语法的可以按照下面的方式去写,效果是一样的
main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
3. 创建文件
在 src
文件中,创建 store
文件,里面按模块创建 ts
文件(也可以是 js
)。
注意: pinia
不需要创建 modules
文件来区分模块化,这是它和 vuex
的区别。
以登录后保存用户信息模块举例:
注意: 命名方式建议统一规范 use + id + store
,示例 useUserStore
,id
为 user
。
store/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: {}
}),
actions: {
SetUserInfo(data: any) {
this.userInfo = data
}
}
})
4. 使用
先引入模块,再将引入的模块对象赋值给变量 store
(命名随意),如果不需要修改数据,用 const
声明变量,需要修改数据则使用 let
声明。
注意:引入的模块对象名要与模块中 export const
声明的一致。
.ts or .vue
import { useUserStore } from '@/store/user'
const store: any = useUserStore()
console.log(store.userInfo)
5. 修改数据
修改数据多种方法,可以直接修改,也可以使用 actions 修改。
方法1:直接修改
.ts or .vue
import { useUserStore } from '@/store/user'
const store = useUserStore()
store.userInfo = obj // obj 指新值
方法2:借助 actions 修改
.ts or .vue
import { useUserStore } from '@/store/user'
const store = useUserStore()
store.SetUserInfo(obj) // obj 指新值
方法3:多属性修改
store/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: null,
age: null,
sex: null,
}),
})
上面的方法都是用来修改单个属性的,如果你需要一次修改多个属性,虽然你可以重复操作上面的方法,但是 pinia 提供了新的方法,我更推荐使用官方推荐的方法。
.ts or .vue
import { useUserStore } from '@/store/user'
const store = useUserStore()
// 你可以这样去修改(不建议)
store.name = '张三'
store.age = 24
store.sex = '男'
// 推荐使用下面这种方式 √
store.$patch({
name: '张三',
age: 24,
sex: '男',
})
修改数据的场景及方法当然不止这些,有些复杂的数据修改仅靠这些是难以实现的,不过本文的目的是简单讲解 pinia
的使用方法,就不多做赘述了,想具体了解推荐去看 Pinia 官方文档。
三、持久化存储
pinia
和 vuex
一样,数据是短时的,只要一刷新页面,数据就会恢复成初始状态,为了避免这个问题,可以对其采用持久化保存方法。
持久化保存的原理是在 pinia
中数据更新时,同步保存到 localStorage
或 sessionStorage
中,刷新后从本地存储中读取数据,你可以选择自己去写,但是实现起来并不像想象中那么容易,当然,也没那么难。
我推荐使用插件去实现持久化存储,这样更便捷,省时省力。推荐插件为 pinia-plugin-persist,当然,实现持久化存储的插件肯定不止这一种,想用别的也无所谓,本文仅对这款插件讲解使用方法。
1. 安装插件
yarn add pinia-plugin-persist
# 或者使用 npm
npm install pinia-plugin-persist
2. 引入插件
和引入 pinia
一样,在 main.ts
中引入。
mian.ts
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
const pinia = createPinia()
pinia.use(piniaPersist)
createApp(App).use(pinia).mount('#app')
3. 使用插件
方式1:默认保存
下面这种写法会将当前模块中的所有数据都进行持久化保存,默认保存在 sessionStorage
中, key
为模块 id
,刷新页面不需要手动读取数据,插件会自动读取。
store/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: null,
age: null,
sex: null,
}),
persist: {
enabled: true // true 表示开启持久化保存
}
})
方式2:设置 key 、指定保存内容
你可以主动设置 key
名,也可以指定哪些数据保存,默认会保存当前模块全部数据。
store/user.ts
export const useUserStore = defineStore('storeUser', {
state: () => ({
name: null,
age: null,
sex: null,
}),
persist: {
enabled: true,
strategies: [
{
key: 'user',
storage: localStorage,
paths: ['name']
},
],
},
})
你甚至可以对不同数据设置不同的本地存储方式。
store/user.ts
export const useUserStore = defineStore('storeUser', {
state: () => ({
name: null,
age: null,
sex: null,
}),
persist: {
enabled: true,
strategies: [
{ storage: sessionStorage, paths: ['name'] },
{ storage: localStorage, paths: ['age'] },
],
},
})
方式3:保存到 cookie
保存到 cookie
中当然也是可以的,不过需要手动添加 cookie
的保存方式,同样,此处也是推荐使用插件 js-cookie 来完成。
npm install js-cookie
store/user.ts
import Cookies from 'js-cookie'
const cookiesStorage: Storage = {
setItem (key, state) {
return Cookies.set(key, state.accessToken, { expires: 3 }) // 设置有效期 3 天,不设置默认同 sessionStorage 有效期一致
},
getItem (key) {
return JSON.stringify({
accessToken: Cookies.get(key),
})
},
}
export const useUserStore = defineStore('storeUser', {
state: () => ({
name: null,
age: null,
sex: null,
accessToken: 'xxxxxxxxx',
}),
persist: {
enabled: true,
strategies: [
{
storage: cookiesStorage,
paths: ['accessToken'] // cookie 一般用来保存 token
},
],
},
})
文章到此就结束了,如果有需要作者补充或修正的,欢迎在评论区留言。
END