Pinia的基本使用
为什么使用Pinia
很多小伙伴可能会抛出一系列的疑问:为什么要学习Pinia?Pinia有什么优点吗?既然Vue3还能使用Vuex为什么我还要学它?
这些问题其实都有答案,我们不可能平白无故的而去学习一样东西吧!肯定它有自己的优点的,所以这里我们先列出Pinia的优点:
- Vue2和Vue3都支持。
- Pinia中只有state、getters、actions,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,Pinia直接抛弃它了,这无疑减少了我们工作量。
- Pinia中actions支持同步和异步,Vuex不支持。
- 良好的Typescript支持,我们知道Vue3都推荐使用TS来编写,这个时候使用Pinia就非常合适了。
- 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而Pinia中每个store都是独立的,互相不影响。
- 体积非常小,只有1KB左右。
- Pinia支持插件来扩展自身功能。
- 支持服务端渲染。
Pina的基础特性:
State
- 默认情况下,通过 store 实例访问 state,可以直接读取和写入,如 @click=“store.count++”。
- 通过 store.$reset() 方法可以将 state 重置为初始值。
- 除了直接通过 store 修改 state,还可以通过 store.$patch() 方法提交多个更改。
Getters
- Getters 属性的值是一个函数,接受 state 作为第一个参数,目的是鼓励使用箭头函数。
- 非箭头函数会绑定 this,建议仅在需要获取整个 store 实例的场景使用,且需要显式定义函数返回类型。
Actions
- 与 Gettes 一样可以通过 this 访问整个 store 实例。
- Actions 可以是异步的或同步的,不管怎样,都会返回一个 Promise。
- Actions 可以自由的设置参数和返回的内容,一切将自动推断,不需要定义TS 类型。
Pinia的基本使用
- 创建一个项目,安装pinia
- 创建store以及使用store
- 添加state以及操作state
- getters属性
- actions属性
因为Pinia基本都是基于Vue3使用,至于Vue2中如何使用,这里就不讲解了,可以自行去Pinia官网学习,毕竟Vue2中使用pinia的还是少数。
地址:https://pinia.vuejs.org/
1.1.创建一个最新的Vue3 + TS + Vite项目
执行命令:npm create vite@latest pinia-vite-demo --template vue-ts
1.2.运行项目:
执行命令:npm install
然后npm run dev
1.3.安装pinia:
执行命令:yarn add pinia 或者使用npm npm install pinia
1.4.安装完成后我们需要将 pinia 挂到 vue 应用中
也就是我们需要创建一个根存储传递给应用程序,简单来说就是创建一个存储数据的数据桶,放到应用程序中去。需要修改main.ts/js文件,引入pinia提供的createPinia方法,创建根存储。
import { createApp } from 'vue' import './style.css' import App from './App.vue' //引入pinia提供的createPinia方法,创建根存储 import {createPinia} from 'pinia' const pinia = createPinia(); const app = createApp(App); app.use(pinia) app.mount('#app')
2.1.创建store,那什么是store呢?
(官网解释)一个 Store (如 Pinia)是一个实体,它持有未绑定到您的组件树的状态和业务逻辑。换句话说,它托管全局状态。它有点像一个始终存在并且每个人都可以读取和写入的组件。它有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。
我们可以把这三个概念理解为vue组件中的“数据”data、“计算”computed和“方法”methods。store简单来说就是数据仓库的意思,我们数据都放在store里面。我们也可以把它理解为一个公共的组件,只不过该公共组件只存放数据,这些数据我们其它所有的组件都能够访问且可以修改。
我们需要使用pinia提供的defineStore()方法来创建一个store,该store用来存放我们需要全局使用的数据。首先在项目src目录下新建store文件夹,用来存放我们创建的各种store,然后在该目录下新建xxx.ts文件,主要用来存放与xxx相关的store,不同的store用来存放不同的全局数据,相当于把它们进行了分类,方便我们更好的管理。一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性。
比如有一个用户相关的数据,我们可以在store目录下创建一个user.ts,还有一个产品相关的数据,再创建一个product.ts,这两个没有关联的数据,我们可以分别给他们创建一个store来管理,代码如下:
//创娃store很简单,调用pinia中的definestore函数即可,该函数族收两个参数: import {defineStore} from 'pinia' //第一个参敬是应用程序中store的唯一id,就是给数据仓库起个名字 //第二个参数是一个对象,store的配置项,比如配置store内的数据,修改数据的方法等等 export const useUsersStore = defineStore('user',{ //其他配置项 })
2.2.使用store
假如我们要在App.vue里面使用它,使用 store 很简单,直接引入我们声明的 useUsersStore 方法即可,我们可以先看一下执行方法输出的是什么:
<script setup lang="ts"> import { useUsersStore } from './store/user'; const store = useUsersStore(); console.log(store) </script>
3.1.添加state
我们都知道store是用来存放公共数据的,我们利用defineStore函数创建了一个store,该函数第二个参数是一个options配置项,我们需要存放的数据就放在options对象中的state属性内。该属性就是用来存储数据的,我们往state中添加了3条数据。需要注意的是,state接收的是一个箭头函数返回的值,它不能直接接收一个对象。
import {defineStore} from 'pinia' export const useUsersStore = defineStore('user',{ //这里的state与vue2中用来存放初始化变量的data的写法相似,需要return state:()=>{ return { name:"不知好歹", age:20, sex:"女", items:[80,90] } }, })
3.2.操作state
3.2.1.读取state数据
我们往store里面存储数据就是为了操作它。首先我们读取一下它的数据,并让它在页面上显示,我们直接通过store.xxx的方式获取到了store存储的值,但是,这样比较繁琐,我们可以用解构的方式来获取值,使得代码更简洁一点。代码如下:
<template> <p>姓名:{{ name }}</p> <p>年龄:{{ age }}</p> <p>性别:{{ sex }}</p> </template> <script setup lang="ts"> import { useUsersStore } from './store/user'; import {storeToRefs} from 'pinia'//响应式改变数据状态 const store = useUsersStore(); const {name,age,sex,items} = storeToRefs(store); </script>
3.2.2. 多个组件使用state数据
我们使用store最重要的目的就是为了组件之间共享数据,那么接下来我们新建一个child.vue组件,在该组件内也使用state数据,跟App.vue几乎一样,代码如下:
<template> <h1>我是Child组件</h1> <p>姓名:{{ name }}</p> <p>年龄:{{ age }}</p> <p>性别:{{ sex }}</p> </template> <script setup lang="ts"> import { useUsersStore } from './store/user'; import {storeToRefs} from 'pinia'//响应式改变数据状态 const store = useUsersStore(); const {name,age,sex,items} = storeToRefs(store); </script>
3.2.3. 修改、重置、批量修改以及替换state数据
想要修改store中的数据,可以直接重新赋值即可,重置只要调用store.$reset() 方法即可,而批量修改也有更简便的方法,使用store的patch()方法就行了,patch()有两种用法:①只传需要修改的数据就可以了,②可以使用patch的函数参数用法, 最后就是替换整个state,store.state(用的较少),利用pinia的storeToRefs函数,就可以将state中的数据变成响应式的,代码如下:
<template> <p>姓名:{{ name }}</p> <p>年龄:{{ age }}</p> <p>性别:{{ sex }}</p> <button @click="changeName">更改姓名</button> <button @click="reset">重置state</button> <button @click="patchStore">批量修改</button> <button @click="thstore">替换store</button> <!-- <child></child> --> </template> <script setup lang="ts"> // import child from './child.vue' import { useUsersStore } from './store/user'; import {storeToRefs} from 'pinia' const store = useUsersStore(); const {name,age,sex,items} = storeToRefs(store); //更改state数据 const changeName = () =>{ store.name = "张三"; console.log(store) } //重置state const reset =()=>{ store.$reset(); } //批量修改store,传想要更改的数据就可以 const patchStore = () =>{ //普通用法 // store.$patch({ // name:"呜小游", // age:27, // }) //函数用法 store.$patch((state)=>{ state.name = '鹿小优' state.items.push(100) }) } //替换state const thstore = () => { store.$state = { name:"艾斯", age:36, sex:"男", items:[666] }; }; </script>
4.1.getters属性
getters是defineStore参数配置项里面的另一个属性,getter属性值是一个对象,该对象里面是各种各样的方法,跟Vue中的计算属性类似,它的作用就是返回一个新的结果。当然我们这里的getter就是处理state数据。
4.2.添加getter
我们在配置项参数中添加getter属性,我们在该属性对象中定义一个getAddAge方法,该方法会默认接收一个state参数,也就是state对象,然后该方法返回的是一个新的数据。代码如下:
import {defineStore} from 'pinia' export const useUsersStore = defineStore('user',{ //这里的state与vue2中用来存放初始化变量的data的写法相似,需要return state:()=>{ return { name:"不知好歹", age:20, sex:"女", items:[80,90] } }, getters:{ getAddAge:(state) =>{ return state.age + 80; }, }, })
4.3. 使用getter
可以直接在标签上使用了store.gettAddAge方法,这样可以保证响应式,当我们点击修改数据按钮时,页面上的新的年龄字段也会跟着变化。代码如下:
4.4.getter中调用其它getter
我们再定义了一个名为getNameAndAge的getter函数,我们这里不使用箭头函数的形式,因为我们想在函数内部使用this,箭头函数的this指向问题相信大家都知道吧!所以这里没有采用箭头函数的形式。而是在函数内部直接使用this来获取state数据以及调用其它getter函数,这里this指向的是store实例,所以我们可以直接在getter方法中调用this。代码如下:
4.5.getter传参
既然getter函数做了一些计算或者处理,那么我们很可能会需要传递参数给getter函数,但是我们前面说getter函数就相当于store的计算属性,和vue的计算属性差不多,我们都知道Vue中计算属性是不能直接传递参数的,所以我们这里的getter函数如果要接受参数的话,也是需要做处理的。
5.1.actions属性
转: https://blog.csdn.net/qq_44505797/article/details/130407908