vue新的状态管理器Pinia
阅读数:129 评论数:0
跳转到新版页面分类
html/css/js
正文
一、概述
Pinia是为vue开发的一个全新的状态管理器。
1、vuex
State、Getters、Mutations(同步)、Actions(异步)
Vuex4用于vue3
Vue3用于vue2
2、pinia
State、Getters、Actions(同步异步)
即支持vue2也支持vue3。
二、Pinia核心特性
1、没有Mutation
2、Action支持同步和异步
3、没有模块的嵌套结构
pinia通过设计提供扁平结构,就是说每个store都是互相独立的。
4、更好的typescript支持
5、无需手动添加store,它的模块默认情况下创建就自动注册的。
6、支持vue devtools
三、pinia使用
以vue3+typescript为例
1、安装
npm install pinia
2、main.js初始化配置
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app')
3、在store目录下创建一个user.ts为例,我们先定义并导出一个名为user的模块
import { defineStore } from 'pinia'
export const userStore = defineStore('user', {
state: () => {
return {
count: 1,
arr: []
}
},
getters: { ... },
actions: { ... }
})
defineStore接收两个参数:
第一个参数是模块的名称,必须是唯一的,pinia会把所有模块都挂载到根容器下。
第二个参数是一个对象,里面的选项和vuex差不多
(1)state用来存储全局状态,使用箭头函数为了更好的ts类型推导
(2)getters 封装计算属性,它有缓存的功能,getters函数的第一个参数是state对象
// 相当于 vue 中的 computed 计算属性
getters: {
// 定义的 getters,第一个参数就是该容器的 state
comp(state) {
return ++state.count
},
// getter也可以接受其他getter作为第二个参数
do2(state,otherGetter){
...
}
},
在pinia中定义常规函数时通过this访问整个store的实例,可以通过this访问其他getter。
在页面组件中可以直接去调用该容器的getters方法
<template>
<!-- 后面相同的调用,都是基于第一次计算的值 -->
<p>{{ mainStore.comp }}</p>
<p>{{ mainStore.comp }}</p>
<p>{{ mainStore.comp }}</p>
</template>
<script setup lang="ts">
// 导入 pinia 实例
import { useMainStore } from '../store/index'
// 实例化容器
const mainStore = useMainStore()
</script>
<style scoped></style>
(3)actions 封装业务逻辑,修改state
4、访问state
由于defineStore会返回一个函数,所以要先调用拿到的数据对象,然后就可以在模板中直接使用了
<template>
<div>{{ user_store.count }}</div>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
// 解构
// const { count } = userStore()
</script>
比如像注释中的解构出来使用,是完全没有问题的,只是注意了,这样拿到的数据不是响应式的,如果要解构还保持响应式就要用到一个方法storeToRefs()
<template>
<div>{{ count }}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { userStore } from '../store'
const { count } = storeToRefs(userStore)
</script>
5、更新状态
更新 state 里的数据有四种方法,我们先看三种简单的更新,说明都写在注释里了
<template>
<div>{{ user_store.count }}</div>
<button @click="handleClick">按钮</button>
</template>
<script lang="ts" setup>
import { userStore } from '../store'
const user_store = userStore()
const handleClick = () => {
// 方法一
user_store.count++
// 方法二,需要修改多个数据,建议用 $patch 批量更新,传入一个对象
user_store.$patch({
count: user_store.count1++,
// arr: user_store.arr.push(1) // 错误
arr: [ ...user_store.arr, 1 ] // 可以,但是还得把整个数组都拿出来解构,就没必要
})
// 使用 $patch 性能更优,因为多个数据更新只会更新一次视图
// 方法三,还是$patch,传入函数,第一个参数就是 state
user_store.$patch( state => {
state.count++
state.arr.push(1)
})
}
</script>
第四种方法就是当逻辑比较多或者请求的时候,我们就可以封装到示例中 store/user.ts 里的 actions 里
可以传参数,也可以通过 this.xx 可以直接获取到 state 里的数据,需要注意的是不能用箭头函数定义 actions,不然就会绑定外部的 this 了
actions: {
changeState(num: number){ // 不能用箭头函数
this.count += num
}
}
// 调用
const handleClick = () => {
user_store.changeState(1)
}
四、pinia固化插件的使用
https://seb-l.github.io/pinia-plugin-persist/
1、安装依赖
npm i pinia-plugin-persist --save --include=dev
// 或者使用 yarn 安装
yarn add pinia-plugin-persist
2、main.js中
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia';
// 下面是我们安装的固化插件。
import piniaPersist from 'pinia-plugin-persist'
const app = createApp(App);
const pinia = createPinia();
pinia.use(piniaPersist);
// 特别注意:固化插件是 pinia.use 并不是 app.use
app.use(pinia);
app.mount('#app')
3、在具体的模块中
默认情况下,如果开启(即为true),整个state都会持久化,如果想要部分状态持久化,需要在两个策略中都进行配置。
import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
state(){
return {
count: 10,
num: 20
}
},
persist: { // 固化插件
enabled: true, // 开启存储
strategies: [ // 指定存储的位置以及存储的变量都有哪些,该属性可以不写,
//在不写的情况下,默认存储到 sessionStorage 里面,默认存储 state 里面的所有数据。
{ storage: localStorage, paths: ["count"] },
// paths 是一个数组,如果写了 就会只存储 count 变量,当然也可以写多个。
]
},
getters:{
},
actions:{
piniaAdd(){
this.count++;
}
}
})