main.ts
import pinia from '@/stores'
app.use(pinia); 引入store/index.ts中的pinia
store/index.ts
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
const pinia = createPinia()
// 永久持久化插件
pinia.use(piniaPersist);
export default pinia
store/user.ts
// 使用持久化存储
import {defineStore} from 'pinia'
import { getMenusApi } from '@/api/user'
import { toRaw } from '@vue/reactivity'
export const useUserStore=defineStore('storeUser',{
state:()=>{
return{
fistName:"",
lastName:"",
accessToken:"",
meunList:<any>[]
}
},
getters:{
getMeunList:(state)=>{
return state.meunList
}
},
actions:{
setToken(value:string){
this.accessToken=value
},
// 获取菜单
getMenus() {
let that=this;
return new Promise((resolve, reject) => {
getMenusApi().then((response:any) => {
that.meunList= [{name:""}];
// that.meunList= JSON.parse(response) ;
console.log("数据00000000000",toRaw(that.meunList))
localStorage.setItem('MerMenuList', JSON.stringify(response))
resolve(response)
}).catch(error => {
reject(error)
})
})
},
},
persist:{
enabled:true //启用插件
}
})
在页面中使用
import {useUserStore} from '@/stores/user'
import { toRaw } from '@vue/reactivity'
//使用vue3.0时,因为底层是使用proxy进行代理的,所以当我们打印一些值的时候,是proxy代理之后的是Proxy对象,Proxy对象里边的[[Target]]才是真实的对象。
let store=useUserStore();
store.getMenus() //调用actions方法
let meunList=toRaw(store.meunList)
//通过vue中的响应式对象可使用toRaw()方法获取原始对象 这样这个数据就可以直接使用了
console.log( meunList,"路由----")
我们发现起始store中的值已经改变了,但是子组件没有响应式,该问题的原因是我们子组件采用了解构的方式调用,而该种方式是不能达到响应式的目的的,但是pinia给我们提供了解决办法。
我们修改一下上面的调用方式-2,调用pinia提供的storeToRefs方法。
<template>
<p>---child---</p>
<p>name:{{name}}</p>
<p>age:{{age}}</p>
<p>sex:{{sex}}</p>
</template>
<script setup lang="ts">
import { useUsersStore } from "../store/user";
import {storeToRefs} from 'pinia'
const store = useUsersStore();
const { name, age, sex } = storeToRefs(store);
</script>
此时可以看见,子组件也是响应式了。完美解决。而两种调用方式(推荐第二种)
5)同时修改多个state里的值
- 面我们修改state的数据是都是一条一条修改的,比如store.name="张三"等等,如果我们一次性需要修改很多条数据的话,有更加简便的方法,使用store的$patch方法,修改app.vue代码,添加一个批量更改数据的方法。
App.vue
<button @click="patchStore2">批量修改数据</button>
// 法一
const patchStore = () => {
store.$patch({
name: "张三",
age: 100
});
};
// 法二(推荐)
const patchStore2 = () => {
store.$patch((state) => {
state.name='张三'
state.age = 99
})
};
3)getters方法中带参数
有时我们需要手动传递参数到方法执行,我们可以如此
user.ts
getters: {
getAddParamsAge: (state) => {
return (params:number)=>state.age + 100 + params;
},
},
App.vue
<p>getters+Params:{{store.getAddParamsAge(500)}}</p>
基本使用之actions
前面我们提到的state和getters属性都主要是数据层面的,并没有具体的业务逻辑代码,它们两个就和我们组件代码中的data数据和computed计算属性一样。
那么,如果我们有业务代码的话,最好就是写在actions属性里面,该属性就和我们组件代码中的methods相似,用来放置一些处理业务逻辑的方法。
actions属性值同样是一个对象,该对象里面也是存储的各种各样的方法,包括同步方法和异步方法。
*1)添加actions(此时的useUsersStore即是最基本的一个架构了)
user.ts
import { defineStore } from 'pinia'
export const useUsersStore = defineStore('users', {
// 其它配置
state: () => {
return {
name: "李华",
age: 25,
sex: "男",
}
},
getters: {
getAddAge: (state) => {
return state.age + 100;
},
getAddParamsAge: (state) => {
return (params:number)=>state.age + 100 + params;
},
getNameAndAge(): string {
return this.name + this.getAddAge;
},
},
actions: {
saveName(name: string) {
// 修改state中的name
this.name = name;
},
},
})
- 调用
App.vue
<button @click="store.saveName('李成功')">action</button>