什么是Pinia
如果你学过Vue2,那么你一定使用过Vuex。我们都知道Vuex在Vue2中主要充当状态管理的角色,所谓状态管理,简单来说就是一个存储数据的地方,存放在Vuex中的数据在各个组件中都能访问到,它是Vue生态中重要的组成部分。
既然Vuex那么重要,那么在Vue3中岂能丢弃! 在Vue3中,可以使用传统的Vuex来实现状态管理,也可以使用最新的pinia来实现状态管理,我们来看看官网如何解释pinia的。
官网解释:
Pinia是 Vue的存储库,它允许您跨组件/页面共享状态。
从上面官网的解释不难看出,pinia和Vuex的作用是一样的,它也充当的是一个存储数据的作用,存储在pinia的数据允许我们在各个组件中使用。
实际上,pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex
为什么使用Pinia
- Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的小伙伴都能很快上手。
- pinia中只有state、getter、action,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,pinia直接抛弃它了,这无疑减少了我们工作量。
- pinia中action支持同步和异步,Vuex不支持
- 良好的Typescript支持,毕竟我们Vue3都推荐使用TS来编写,这个时候使用pinia就非常合适了
- 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而pinia中每玲store都是独立的,互相不影响。
- 体积非常小,只有1KB左右。
- pinia支持插件来扩展自身功能。支持服务端渲染。
使用Pinia
安装pinia
npm install pinia
核心概念
- store:状态仓库
- state:状态,和 vuex 保持一致
- getters:类似组件的计算属性,和 vuex 中的 getters 的保持一致
- actions:和 vuex 中的 actions 保持一致,可以处理逻辑并修改 state
使用步骤
- 创建 pinia
- 注册 pinia
- 创建 store
- 抽离需要管理的数据作为 state,声明 getters 优化状态读取,声明 actions 处理业务逻辑
- 在需要的地方(组件或其他),导入和使用 store
创建 pinia
在store/index.ts文件中创建并返回pinia实例
ts
//引入创建pinia的方法
import { createPinia } from "pinia";
//创建并返回pinia实例
const pinia = createPinia();
export default pinia;
注册 pinia
在mian.ts文件中注册pinia
ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import pinia from './store'
createApp(App).use(pinia).mount('#app')
创建 store
使用 defineStore
方法创建 store
,store
的命名遵循 useXXX
的形式。创建时需要指定一个唯一的 id
。
在store/user.ts文件中创建store
ts
//引入定义store的方法
import { defineStore } from 'pinia'
/**
* 第一个参数是store的唯一id,或者说是模块
* 第二个参数是一个对象,store的配置项,比如store内的数据
*/
export const useUserStore = defineStore("user", {})
state getters actions
在store/user.ts文件中使用state getters actions
ts
export const useUserStore = defineStore("user", {
/**
* 定义当前模块的state
* state是一个函数,必须有返回值,返回值即这个模块的状态
* pinia可以完整的推断出state的类型
* @returns
*/
state() {
return {
/**年龄 */
age: 18,
name: '张三',
}
},
getters: {
/**
* 当前年龄的两倍
* 接收一个参数 ------------ 当前模块的state
* 必须有返回值,返回值就是这个计算属性的结果
* @param state
* @returns
*/
doubleAge: (state) => state.age * 2,
/**
* 在getter中调用其他的计算属性方法
* 不能使用箭头函数的形式
*
* 此处,this关键字指向的是store实例
*
* 还需要自定义函数的返回值类型
* @returns
*/
getNameAndAge() : string {
return this.name + this.age;
},
/**
* 接收页面上传过来的参数
* 计算属性内部返回一个方法,方法接收一个参数,这个参数就是页面传过来的参数
* @returns
*/
getAddAge() {
return (num: number) => this.age + num;
}
},
/*
当前模块的相关方法
存放当前模块的相关的业务逻辑函数
*/
actions: {
/**
* 在pinia中,可以直接通过actions修改state
* pinia中的actions既可以是异步的又可以是同步的
* @param name
*/
saveName(name: string) {
this.name = name;
}
}
})
使用store
state里面的数据是响应式的
在App.vue文件中
ts
<template>
<div>
你好,我是pinia,年龄{{ userStore.age }}
</div>
<div>
<button @click="add">加一</button>
</div>
<div>
计算属性--{{ userStore.doubleAge }}--{{ userStore.getNameAndAge }}
</div>
<div>
计算属性--{{ userStore.getAddAge(11) }}
</div>
<div>
{{ userStore.name }}
<button @click="changeName">修改名字</button>
</div>
</template>
<script setup lang="ts">
import { useUserStore } from './store/user'
const userStore = useUserStore();
/**
* 可以直接操作store中的状态并且重新渲染
* 也就是说state里面的数据是响应式的
*/
const add = () => {
userStore.age++;
}
const changeName = () => {
userStore.saveName('李四');
}
</script>
pinia 持久化
Pinia 的数据是存在内存当中的,页面刷新数据就会丢失。所以对于一些重要数据,需要持久化到本地存储,简单的数据可以直接调用 localStorage
或者 sessionStorage
。更推荐的是使用持久化插件,比如 pinia-plugin-persistedstate
。
在store/index.ts中引入持久化插件
ts
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
pinia.use(piniaPluginPersistedstate)
Pinia
中的状态是以 store
为单位进行管理的。哪个 store
中的数据需要持久化,就在哪个 store
中去开启。比如:
在store/user.ts文件中开启持久化
ts
const useUserStore = defineStore('user', {
persist: true,
// ......
})