2.pinia基本使用
1.首先先安装依赖
2.在main.js中引入pinia并创建容器挂载到根实例上
1 2 3 4 | //引入stores暴露出的pinia的实例 import pinia from './stores' createApp(App).use(pinia).mount( '#app' ) |
3.创建stores文件夹和index.js文件(这个文件以后基本不用管了)
1 2 3 | import { createPinia } from "pinia" ; const pinia = createPinia() export default pinia |
4.在stores文件夹下创建counter.js文件。这个文件就是存有关counter相关的数据。(类似vuex的模块化)
defineStore 是需要传参数的,
- 第一个参数是id,就是一个唯一的值,简单点说就可以理解成是一个命名空间.
- 第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,第二个是 getters,第三个是 actions。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //定义关于counter的store import {defineStore} from 'pinia' /*defineStore 是需要传参数的,其中第一个参数是id,就是一个唯一的值, 简单点说就可以理解成是一个命名空间. 第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state, 第二个是 getters,第三个是 actions。 */ const useCounter = defineStore( "counter" ,{ state:() => ({ count:66, }), getters: { }, actions: { } }) //暴露这个useCounter模块 export default useCounter |
注意:返回的函数统一使用useXXX作为命名方案,这是约定的规矩。例如上面的useCounter
5.然后再组件中使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <template> <!-- 在页面中直接使用就可以了 不用 .state--> <div>展示pinia的counter的count值:{{counterStore.count}}</div> </template> <script setup> // 首先需要引入一下我们刚刚创建的store import useCounter from '../stores/counter' // 因为是个方法,所以我们得调用一下 const counterStore = useCounter() </script> |
注意:在模板使用 ,不用和vuex一样还要.state,直接点state里面的K
运行效果: 可以用vue3的调试工具看pinia
2.1注意Store获取到后不能解构,否则失去响应式
案例需求,点击按钮加一:
一个不解构,一个不解构看看区别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <template> <div>展示pinia的counter的count值:{{counterStore.count}}</div> <div>展示解构出来的pinia的counter的count值:{{count}}</div> <button @click= "addCount" >count+1</button> </template> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() const {count} = counterStore function addCount(){ //这里可以直接操作count,这就是pinia好处,在vuex还要commit在mutaitions修改数据 counterStore.count++ } <script/> |
在 vuex 里面是坚决不允许这样子直接操作 state 数据的,pinia是可以的,看看上面的addCount函数直接操作。
运行结果:
解决方案:
pinia提供了一个函数storeToRefs解决。引用官方API storeToRef 作用就是把结构的数据使用ref做代理
1 2 3 | import {storeToRefs} from 'pinia' const counterStore = useCounter() const {count} = storeToRefs(counterStore) |
现在数据都是响应式的了
3.修改state的数据
重新新建一个user模块
stores/user.js
1 2 3 4 5 6 7 8 9 10 11 | //定义一个关于user的store import {defineStore} from 'pinia' const useUser = defineStore( "user" ,{ state:()=>({ name: "紫陌" , age:18 }) }) export default useUser |
组件中修改数据:
**第一种方法:**点击按钮修改数据,这种方法是最直接的修改数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <template> <div> <h2>名字是:{{name}}</h2> <h2>年龄是:{{age}}</h2> <button @click= "updateStore" >修改Store数据</button> </div> </template> <script setup> import useUser from '../stores/user' import {storeToRefs} from 'pinia' const userStore = useUser() const {name,age} = storeToRefs(userStore) function updateStore(){ //一个个的修改状态 userStore.name = "zimo" userStore.age = 20 } |
效果:点击也修改了
第二种方法:$patch函数修改
1 2 3 4 5 6 7 8 9 10 11 | function updateStore(){ //一个个的修改状态 // userStore.name = "zimo" // userStore.age = 20 // 一次性修改多个状态 userStore.$patch({ name: "zimo" , age:20 }) } |
这个方式也可以,效果一样。
第三种方法:$state 方式(这个是替换的方式。)这个基本不用,这里就不多说。可以看查阅文档。
第四种方法:$reset()函数是重置state数据的
新增一个重置按钮:
1 2 3 | function resetStore(){ userStore.$reset() } |
运行结果:点击了修改数据按钮之后在点重置按钮就恢复原始的数据。
4.getters的使用
getters 类似于 vue 里面的计算属性,可以对已有的数据进行修饰。不管调用多少次,getters中的函数只会执行一次,且都会缓存。
1.最基本的使用
在counter模块演示了,counter模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //定义关于counter的store import {defineStore} from 'pinia' const useCounter = defineStore( "counter" ,{ state:() => ({ count:66, }), getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, }, }) //暴露这个useCounter模块 export default useCounter |
组件中:
1 2 3 4 | < div > < h1 >getters的使用</ h1 > < h2 >doubleCount:{{counterStore.doubleCount}}</ h2 > </ div > |
运行效果:
这样就是最基本的使用了。
2.一个getter引入另外一个getter
couter模块:
1 2 3 4 5 6 7 8 9 10 11 12 | getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, //一个getter引入另外一个getter doubleCountAddTwo(){ console.log( this ); //this.是store实例 return this .doubleCount + 2 } }, |
组件中使用:
1 2 3 4 5 | < div > < h1 >getters的使用</ h1 > < h2 >doubleCount:{{counterStore.doubleCount}}</ h2 > < h2 >doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</ h2 > </ div > |
运行效果并且看看打印的this:
3.getters中用别的store中的数据
在counter模块中拿user模块的store数据。
count模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | //定义关于counter的store import {defineStore} from 'pinia' import useUser from "./user" const useCounter = defineStore( "counter" ,{ state:() => ({ count:66, }), getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, //一个getter引入另外一个getter doubleCountAddTwo(){ console.log( this ); //this.是store实例 return this .doubleCount + 2 }, //getters中用别的store中的数据 showMessage(state){ console.log(state); console.log( this ) //获取user信息,拿到useUser模块 const userStore = useUser() //拼接信息 return `name:${userStore.name}--count:${state.count}` } }, }) //暴露这个useCounter模块 export default useCounter |
注意:要引入user模块
组件中:
1 2 3 4 5 6 | < div > < h1 >getters的使用</ h1 > < h2 >doubleCount:{{counterStore.doubleCount}}</ h2 > < h2 >doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</ h2 > < h2 >showMessage:{{counterStore.showMessage}}</ h2 > </ div > |
运行结果:
注意:我打印了this和store,他们都是当前这这个模块的实例
这样就在counter模块拿到了user模块的数据了。
5. actions的使用
actions 是可以处理同步,也可以处理异步,同步的话相对来说简单一点.actions类似methods
1.先看同步使用:
counter模块使用:
在actions定义了两个函数一个加一的函数,一个加20的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //定义关于counter的store import {defineStore} from 'pinia' const useCounter = defineStore( "counter" ,{ state:() => ({ count:66, }), actions:{ increment(state){ //actions没有state,只能通过this拿store,这里打印 console.log(state); this .count++ }, incrementNum(num){ this .count += num } } }) //暴露这个useCounter模块 export default useCounter |
组件中:
actions函数在组件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <div> <h1>actions的使用</h1> <h2>count的事值:{{counterStore.count}}</h2> <button @click= "changeState" >count+1</button> <button @click= "incrementNum" >count+20</button> </div> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() function changeState(){ counterStore.increment() } function incrementNum(){ counterStore.incrementNum(20) } </script> |
运行结果并且看看state是什么
初始值是66,点了一次加1和点了一次加20
注意:state的结果是undefined 所以actions只能通过this访问store。getter的话state和this都能访问。
2.异步操作使用
在 actions 处理异步的时候呢,我们一般是与 async 和 await 连用。
counter模块: 这里大致演示,具体还看自己怎么使用。
state:() => ({
count:66,
list:[]
}),
actions:{
//大概演示这个异步流程
async axiosData(){
const res = await fetch("http://-----------------")
if(code ==200){
//收到数据保存到store
this.list = res.data.list
return "ok"
}
}
}
组件使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <template> <!-- 遍历store的数据 --> <div v- for = "item in counterStore.list" ></div> </template> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() counterStore.axiosData().then(res =>{ console.log( "成功" ,res); }) </script> |
就这样可以啦!!!
是不是比vuex简洁很多。。。
6.数据的持久化
pinia支持扩展插件
我们想实现数据持久化
npm i pinia-plugin-persist
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | export const useUserStore = defineStore({ state () { return { count: 0, num: 101, list: [1, 2, 3, 4 ] } }, persist: { enabled: true , // 开启缓存 默认会存储在本地localstorage storage: sessionStorage, // 缓存使用方式 paths:[] // 需要缓存键 } }) Vue3中的pinia使用方法总结(建议收藏版)_vue.js_脚本之家 |