前言
之前在做项目的时候使用的都是Vuex,在学习使用了Vue3之后,在网上看到不少有关Vue3+pinia的搭配,也略微了解到了pinia 的优势,于是自己也想要摸索着学习pinia。
初始化配置🥊🥊
首先准备一个Vue3的项目(这里没有强制要求,因为pinia也可以适配Vue2)并且这里我使用的语言是ts,因为在pinia中和ts兼容做的非常不错,这里考虑使用ts。
当然这里脚手架使用的是vite
npm create vite@latest
然后根据提示一步步的完成初始化工作,之后安装pinia
npm i pinia
在安装完pinia之后,我们就需要在main.ts中进行引用和一些相关的配置
import { createApp } from "vue"; import "./style.css"; import { createPinia } from "pinia"; // 创建pinia实例 const pinia = createPinia(); import App from "./App.vue"; const app = createApp(App); // 将pinia挂载到app上面 app.use(pinia); app.mount("#app");
这里面就是简单的将pinia进行实例化操作,然后将实例化之后的pinia注册到app上面。
以上就是一些简单的初始化的配置工作,下面就开始学习pinia的基本使用方法。
pinia的基本使用⚡️⚡️
初始化store
import { defineStore } from "pinia"; export const useMainStore = defineStore("main", { state: () => { return {}; }, getters: {}, actions: {}, });
- 和使用Vuex一样,首先我们在src文件夹下面新建一个store文件夹,然后在里面新建一个index.ts文件
- 然后在index.ts文件中写入上述的代码,下面我将逐一讲解为什么这么做:
- 首先我们要先导入
pinia
中的defineStore
,这个函数一共接受两个参数,第一个参数相当于是容器的ID,这个值必须唯一,因为最后Pinia
会将所有的容器挂载到根容器上面,第二个参数就是选项对象 - 然后我们就可以在选项对象中配置
state
,getters
和actions
了,这里要强调一点的是state要是一个函数,而且要是一个箭头函数,之所以要是函数的原因就是为了在服务端渲染的时候避免交叉请求导致的数据状态污染,而要求是箭头函数的目的则是为了更好的进行TS类型推断 - 这里要说明的是
pinia
里面是没有mutations
的,这个是pinia
和vuex
最不同的地方之一,在pinia
中取消了mutations
这个用来修改state
值的东西,而是直接使用actions
中的函数来直接进行修改。 - 而
getters
还是基本和Vuex
一样,也是用来存储计算属性,相当于是一个缓存的作用。
在组件使用
以上就是pinia的基本架子,下面我们进一步说明如何在组件中使用pinia
<template> {{ mainStore.count }} {{ mainStore.str }} <hr /> <p>{{ count }}</p> <p>{{ str }}</p> </template> <script setup lang="ts"> import { useMainStore } from "../store/index"; import { storeToRefs } from "pinia"; const mainStore = useMainStore(); // 通过解构的方式获取state中的值 const { count, str } = storeToRefs(mainStore); console.log(count.value); </script>
这里先简单演示一下如何使用:
- 首先我们接收一下在store/index.ts中导出的
1useMainStore函数
,这个函数其实就是defineStore
函数实例化,然后这里面可以读取state中的值,我们同样可以在页面中进行渲染。而且使用之后会有提示(以前使用Vuex没有提示,这个很舒服) - 值得注意的是当我们想要通过解构的方式来获取state中的值的时候,我们需要使用
pinia
中的APIstoreToRefs
,学过Vue3的同学相信不陌生,如果我们直接解构reactive中的值的话,那样会失去响应式,所以我们会使用toRefs这个API来使其保留相应式。在pinia中也是类似,我们使用pinia给我们提供好的API来保留响应式。
状态的更新和actions的使用
上面我们讲述了如何在组件中简单的使用pinia,我们只是讲解了一下如何进行数据的渲染工作,下面我们就来讲述一下如何进行状态的更新以及如何使用actions。
<template> {{ mainStore.count }} {{ mainStore.str }} {{mainStore.arr}} <button @click="handleClick">修改state中的值</button> </div> </template> const handleClick = () => { // 第一种,直接进行更新 mainStore.count++; mainStore.str="hello"; mainStore.arr.push(4); // 第二种:进行批量的更新,这样做可以进行性能的优化 mainStore.$patch({ count: mainStore.count + 1, str: "hello", }); // 第三种:还是通过$patch但是传递的是函数 mainStore.$patch((state) => { state.count++; state.str = "hello"; state.arr.push(4); }); // 第四种:这一种就是使用actions了 mainStore.editState(4); }; //-----------------------------------store/index.ts中的actions actions: { editState(num: number) { this.count += num; this.str = "hello"; this.arr.push(4); }, },
- 这里面一共列举了四种更新pinia中state值的办法,这里我将逐一讲解:
- 首先就是第一种方式,这种方式没有什么好说的,就是直接调用mianStore来直接进行更新操作,包括对count值的修改,对str字符串的修改,对数组数据进行直接的追加,都可以直接进行。
- 其次就是第二种上面列举的第二种方式,我们使用
$patch
方法,我们传递一个对象,来对state中数据进行修改,使用的方式就如同我演示的那样,但是这种方式无法对数组进行修改,这就引出下一种方式 - 这种方式其实还是使用
$patch
,但是这一次我们传入一个函数,这个函数中的参数state其实就是我们在store/index.ts中创建的state,在这里我们同样可以进行批量的修改。 - 那么有人要问这个
$patch
方法和我们普通的进行修改有什么区别呢?其实在这个方法内部中进行了性能优化操作,比如我们使用这种方式我们可以进行批量的修改(就比如只进行一次的视图更新,避免重复更新) - 最后一种方式就是使用actions函数了,其实使用actions一般是执行逻辑比较复杂的操作的时候,这里进行一下演示,我们需要在store/index.ts中进行定义,然后我们在组件页面中使用的时候,我们可以进行传值。然后在store中进行相关的更新操作。
- 使用actions的时候,需要注意我们要将actions中的函数定义成一般函数类型,不要定义为箭头函数类型,因为这样的话this就会指向错误,这是一个注意点。
getters的使用
我们在Vuex中也会经常的使用getters,在pinia
中这个getter
s基本和vuex
中的类似,下面我们来演示一下如何使用
getters: { getCount(state) { console.log("getCount被调用了"); return state.count + 18; }, // 如果在getters中使用了this,那么就必须手动添加返回值类型,否则TS就不能正常的类型推导 getCount(): number { console.log("getCount被调用了"); return this.count + 18; }, },
在pinia
中getters
和vuex
一样具有数据缓存的功能,比如如果我们在一个组件里面多次使用同一个getters
,那么只会被调用一次。这就表明pinia
中也使用了数据缓存。
<template> <p>{{ mainStore.getCount }}</p> <p>{{ mainStore.getCount }}</p> <p>{{ mainStore.getCount }}</p> </template> <script setup lang="ts"> import { useMainStore } from "../store/index"; const mainStore = useMainStore(); </script>
至于getters
的使用场景相信大家并不陌生,getters通常是使用在多个组件中,这些组件都公用一个数据的时候,那么我们可以将这个数据存放到getters中,这样这些组件就共享使用了这个数据,而且这个数据具有计算属性,是响应式的。
结语🌲🌲
这些就是针对pinia进行入门教程,相信通过这个教程,你会有所收获,笔者也是在边学习边总结,相信我们都会有收获。