Vue3状态管理之Pinia使用详解
Vue3带来了一些令人兴奋的新特性,其中之一是Pinia,一个专为Vue3设计的状态管理库。在本文中,我们将深入了解Pinia的使用,包括安装、创建 store、使用状态、以及一些高级功能。在Vue2中,若要使用状态管理器,几乎是必须集成Vuex。首先要明确一点,Vuex在Vue3项目中仍然能够正常使用,是Vue项目中的主力军。然而,我们今天要探讨的是小巧而强大的Pinia。Pinia目前已成为Vue官方正式支持的状态库,不仅适用于Vue2,也同样适用于Vue3。你可以简单地将Pinia视为 Vuex5,是Vue3项目的首选。当然,许多公司或项目在从Vue2转向Vue3时,由于开发习惯了Vuex,因此在Vue3项目中继续使用Vuex的情况也并不罕见。选择使用Pinia还是Vuex取决于实际开发项目情况。
Pinia的概念(小菠萝)
Pinia
是一个为Vue提供状态管理的库。它专注于提供简洁、强大、可扩展的状态管理解决方案。Pinia
是Vue3官方支持的状态管理库,同时也兼容Vue2。Pinia
的设计目标是在开发大型应用时提供更好的性能和开发体验。它采用了一些现代化的状态管理理念,并通过一些独特的特性使得开发者更容易组织和维护项目的状态管理。
Pinia中文官网地址:https://pinia.web3doc.top/
Pinia的优点
pinia
符合直觉,易于学习。pinia
是轻量级状态管理工具,大小只有1KB.pinia
模块化设计,方便拆分。pinia
没有mutations
,直接在actions
中操作state
,通过this.xxx
访问响应的状态,尽管可以直接操作state
,但是还是推荐在actions
中操作,保证状态不被意外的改变。store
的action
被调度为常规的函数调用,而不是使用dispatch
方法或者是MapAction
辅助函数,这是在Vuex
中很常见的。- 支持多个
store
。 - 支持
Vue devtools
、SSR
、webpack
代码拆分。
Pinia的安装
在Vue3项目中,首先需要安装Pinia
。使用以下命令:
1 | npm install pinia |
或者使用 yarn:
1 | yarn add pinia |
Pinia的使用
安装完Pinia
后,接下来就是使用了。在使用的初始步骤中,我们需要在项目中引Pinia
。
Pinia导入
首先在main.js
文件中引入
vue3写法:
1 | import { createPinia } from 'pinia' |
vue2写法:
1 | import { PiniaVuePlugin } from 'pinia' |
我们将继续使用Vue3来详细介绍Pinia
的使用方法。在导入Pinia
时,我们需要使用Vue的hook
,并确保调用它。一旦调用完成,状态将以插件的形式存在于项目中,最后的步骤是在项目中使用这些状态。经过上述步骤的编写,我们成功地在Vue3
项目中导入和配置了Pinia
,为后续的状态管理操作做好了准备。
1 | import { createApp } from 'vue' |
Pinia基本用法
创建index.js文件
首先,在根目录下创建一个 store
文件夹,这个结构对于熟悉Vuex的开发者来说应该很熟悉,毕竟Pinia
的设计就是为了替代Vuex
。创建完 store
文件夹后,在其中新建一个 JavaScript
或TypeScript
文件,命名为 index.js
或index.ts
,为了方便大家直接理解,我这里创建的index.js
文件。
编写index.js文件
defineStore
有三个参数:第一个是state
,第二个是getters
,第三个是actions
。
state
和之前我们vuex
里面的写法是不一样的,在vuex
里面呢,state
是一个对象,但是在pinia
中,state
必须是一个箭头函数,然后在返回一个对象。getters
模块呢,类似于计算属性,是有缓存的,主要是帮助我们修饰一些值。actions
呢,类似于 methods,帮助我们做一些同步的或者是异步的操作,提交state
之类的。
index.js文件:
1 | import { defineStore } from "pinia" |
store_name.js文件:
1 | export const enum Names { |
到这个地方为止,其实我们已经可以使用pinia
了,我们写一个页面使用一下pinia
的值。
1 | <template> |
修改Pinia的值
修改Pinia
的值有多种方式,我们逐一介绍。实际上,修改Pinia
中的值就是修改其状态(state)的值。在上个案例中,我们创建了一个状态(state),其中包含了两个值,一个是 name
,另一个是 age
。今天我们的任务是实现修改Pinia
中状态的值。有许多常见的修改值的方式,我们将逐一进行讲解,一共有五种。
方式一:直接修改
这种方式简单粗暴,直接修改即可,在vuex
里面是坚决不允许这样子直接操作state
数据的,但是小菠萝是可以操作。比如,上个案例,我们来实现点击按钮的时候实现age
加1
操作。
1 | <template> |
方式二:$patch 函数修改
在我们实例化const userInfo = useInfoStore()
这个state
的时候,其实这个userInfo
中,有一个方法,就是patch
函数,它可以帮助我们批量修改。比如点击按钮,同时修改name
和age
的值,直接上代码:
1 | <template> |
方式三:$patch 函数修改
和方式二相同都是使用patch
函数来实现修改,但是有区别,方式二是在patch
函数中传入修改的对象值,但是这种方式传入的是一个函数,其作用可以进行逻辑操作,比如说判断之类的。
1 | <template> |
方式四:$state 方式
这种方式不是很常用,尽管它也可以修改state
的值,但是这种方式有一个很大的弊端,它是直接替换掉state
。比如上面的state
里面有两个值,一个是name
,一个是age
,如果我们只想修改age
的值,那么我们必须把age
和name
的值都写上才可以,如果只写age
,那么name
的值就没有了。
1 | <template> |
方式五: action 方式
这个方式我们需要借助actions
来实现,所以说我们需要去store
文件夹下的index.js
文件中写一个action
。
1 | import { defineStore } from "pinia"; |
写完action
就可以使用action
的方式修改age
的值了。只需要使用实例去调用刚才写的action
函数就行了。
1 | <template> |
action
是可以传参的,修改一下index.js
文件编写的action
函数,让它接受一个参数再赋值。
1 | actions: { |
页面代码修改:
1 | // 方式五 |
pinia的解构
上面的案例,实例化const userInfo = useInfoStore()
了以后呢,这个userInfo
是可以继续解构操作。但是有个问题,就是解构后的数据,是不具备响应式的,即我们修改了state
的值,页面数据不会跟着变化,因为解构后的不是响应式数据。官方提供了一个方法,可以把解构后的数据转换为响应式的数据。就是 storeToRefs
,使用这个方法把我们解构的对象包裹一下就可以了,这个方法其实就是toRefs
类型.
1 | <template> |
Pinia 的 actions
actions
具备处理同步和异步操作的能力。同步操作相对较为简单,上面我们已经通过一个同步的 action
修改了 state
。
actions 异步
先模拟一个异步函数,比如常见的登录。
1 | const User = { |
然后我们在actions
中就可以调用这个异步的操作了,在 actions
处理异步的时候呢,一般是与 async
和 await
连用。
index.js文件:
1 | import { defineStore } from "pinia" |
login.vue页面代码:
1 | <template> |
getter 函数
getters
类似于 vue
里面的计算属性,可以对已有的数据进行修饰,在pinia
中有两种写法。
普通函数方式写法
1 | getters: { |
相互调用
getter
也是可以像 actions
一样相互调用
1 | getters: { |
API 的使用
pinia
里有很多的 API,下面将介绍几种常见的API
$reset :重置到初始值
这个 $reset
可以将 state
的数据初始到初始值,比如有一个数据,点击按钮改变了,然后可以通过这个 API ,将数据恢复到初始状态值。
1 | <template> |
$subscribe:监听 state 数据变化
$subscribe
使用来监听的,监听 state
数据的变化,只要 state
里面的数据发生了变化,就会自动走这个函数。
1 | <template> |
$onAction:一调用 actions 就触发
action
一调用就会被触发,它里面有一个参数 args
,这个args
是 actions
传进来的参数。
1 | // $onAction |
上面的案例只传了一个参数,就是一个工厂函数,其实他还有第二个参数true
,传true
的意思是当这个组件销毁了,这个onAction
还可以继续保活。
1 | // $onAction |
不止 $onAction
可以传第二个参数,$subscribe
也有第二个参数,只不过subscribe
的参数是一个对象,对象里面设置的是detached
为true
效果和onAction
是一样的,当然还有其它的参数,和 watch
是类似的。
1 | userInfo.$subscribe((args, state) => { |
总结
总体来说,Pinia
是一个为 Vue
开发者提供了更灵活、更强大的状态管理工具,尤其在大型应用的状态组织和维护方面具有优势。另外Pinia
还有一些关键特点:
Vue 3 官方支持: Pinia 是 Vue.js 团队官方支持的状态管理库,因此能够充分发挥与 Vue 3 的集成优势。
适用于 Vue 2 和 Vue 3: Pinia 不仅兼容 Vue 3,还可以在 Vue 2 项目中使用,这对于逐步迁移项目或在不同版本间共享代码的项目非常有用。
Typescript 支持: Pinia 提供了完整的 TypeScript 支持,使得开发者在使用 TypeScript 编写代码时能够获得更好的类型提示和开发体验。
零依赖: Pinia 设计为零依赖,不依赖 Vuex 或其他状态管理库。这使得 Pinia 在体积和性能上都更加轻量。
响应式: Pinia 使用 Vue 3 的响应式系统,确保状态的变化能够正确地反映在视图上。
插件体系: Pinia 提供了插件体系,可以轻松扩展其功能。这使得开发者可以根据具体需求引入额外的功能或定制化行为。