胖蔡说技术
随便扯扯

Vue新一代的轻量级状态管理Pinia,你了解吗?

Pinia 是一个 Vue 的存储库, Pinia最初是一个实验,它的作者是Vue.js核心团队的成员,本来是为了测试Vuex5提案而出现的,在2019年11月左右重新设计的Vue状态管理以适用于 Composition API,它不但支持Vue3也支持Vue2options API,也是下一代的轻量级状态管理库。

Pinia是vue的官方核心开发成员开发的,天然对vue是支持的,设计也非常接近vuex5的提案,甚至vuex5的部分灵感都是来自于pinia,目前你就可以把它当做是vuex5来看。

Vuex

既然说是Vuex5,先来看看vuex4的问题:

1、改变一个state的值,如果是同步更新需要mutations,异步的时候需要在actions
2、给Vuexstate添加typescript,需要自定义复杂的类型来支持ts
3、把vue想中的state分成多个部分,就需要用到 module
4、从vue3开始。getters的结果不会像计算属性那样缓存了
5、vuex4.X有一些与类型安全相关的问题

Pinia

如下总结了PiniaVuex来说有哪些优势:

1、Vue2Vue3都支持,支持两种语法创建 Store:Options Api Composition Api

2、pinia中只有state、getter、action,抛弃了Vuex中的Mutation

3、piniaaction支持同步和异步,Vuex不支持

4、良好的Typescript支持

5、无需再创建各个模块嵌套了,Vuex中如果数据过多,通常分模块来进行管理,稍显麻烦,而pinia中可以构建多个store,打包管理会自动拆分

6 .体积非常小,只有1KB左右。 pinia支持插件来扩展自身功能。 支持服务端渲染。

Vuex的代码分割: 打包时,vuex会把3个store合并打包,当首页用到Vuex时,这个包会引入到首页一起打包,最后输出1个js chunk。这样的问题是,其实首页只需要其中1个store,但其他2个无关的store也被打包进来,造成资源浪费。

Pinia的代码分割: 打包时,Pinia会检查引用依赖,当首页用到main store,打包只会把用到的store和页面合并输出1个js chunk,其他2个store不耦合在其中。Pinia能做到这点,是因为它的设计就是store分离的,解决了项目的耦合问题。

Pinia使用

安装

$ yarn add pinia
 # 或者使用npm
$ npm install pinia

使用示例

import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'

// 创建Pinia实例
const pinia = createPinia()
// 实例化 Vue
createApp(App)
.use(pinia) // 挂载到Vue根实例上
.mount('#app') // 挂载在真实 DOM

store的定义是通过 defineStore 函数,它需要一个唯一的名称,该名称可以作为第一个参数传递,也可以用 id 熟悉传递。

store 是一个 reactive 对象,所以不需要 “.value”,也不能对其进行解构使用,否则失去响应性。如果一定要对其进行解构使用,可以使用 storeToRefs ,类似 vue3 中的 toRefs

操作store

1、直接修改

2、批量修改 借助$patch方法

3、批量修改 依然借助$patch方法 利用回调函数处理数组等

4、整个替换 利用$state方法

5、重置 利用$reset方法

监听

可以通过$subscribe()store的方法观察状态及其变化,类似于 Vuex subscribe 方法。该方法的第一个参数接受一个回调函数,该函数可以在 state 变化时触发。

  • events : 是这次state改变的具体数据,包括改变前的值和改变后的值等等数据
  • storeId :是当前store的id
  • type:type表示这次变化是通过什么产生的,主要有三个分别是
    • “direct” :通过 action 变化的
    • ”patch object“ :通过 $patch 传递对象的方式改变的
    • “patch function” :通过 $patch 传递函数的方式改变的

store.$subscribe() 的方法的第二个参数options对象,是各种配置参数,包括
detached属性,其值是一个布尔值,默认是 false, 正常情况下,当 订阅所在的组件被卸载时,订阅将被停止删除,如果设置detached值为 true 时,即使所在组件被卸载,订阅依然可以生效。

取消监听

mainStore.$subscribe返回的值(即上方示例的 subscribe 变量)可以停止订阅。

取值

Getters 把状态传进去,返回经过一系列计算或重组的其他状态,保持响应式。类似组件的computed 用于封装计算属性,有缓存的功能,getters的第一个参数是state

Getters 把状态传进去,返回经过一系列计算或重组的其他状态,保持响应式。

传参

调用

1、同一个store里面直接调用

2、不同的store,调用其他的getter

更新操作

用于修改数据,有点儿类似 methods 的概念;action 定义的函数可以是普通函数从而可以通过 this 访问整个store实例,同时该函数可以传入任意参数并返回任何数据。

注意actions中的方法,可以通过 this 访问到整个存储实例,所以这个时候就不能使用箭头函数,因为箭头函数内部的this指向就是外部。

监听action

通过 store.$onAction(),可以监听action的动作及结果等:

  • name — action 函数的名称
  • store — store 实例,这里是 mainStore
  • args — action 函数参数数组
  • after, — 钩子函数,在action函数执行完成返回或者resolves后执行
  • onError– 钩子函数,在action函数报错或者rejects后执行

可以通过调用 mainStore.$onAction 返回的值来手动停止订阅;store.$onAction 默认在所在组件卸载时会被自动删除,可以通过传递第二个参数 true,来将action订阅和所在组件分开(即组件卸载时,订阅依然有效)。

Pina插件

pinia store 支持扩展,通过 pinia 插件我们可以实现以下:

  • store 添加新属性
  • store 添加新选项
  • store 添加新方法
  • 包装已存在的方法
  • 修改甚至删除actions

1、创建一条静态的属性

2、在所有的store都可以访问到上面添加的text属性

3、pinia插件是一个函数,可以选择返回要添加到store中的属性,它接收一个可选参数,context

  • app : 当前应用 Vue.createApp() 创建的 app
  • options : defineStore 配置的数据
  • pinia : 当前通过 createPinia() 创建的 pinia 实例
  • store :当前 store 实例

4、添加一个内部属性

5、添加一个外部属性

当需要添加来自其他库或不需要响应式的数据时,应该用 markRaw() 包装传递的对象。markRaw 来自 vue3,可以标记一个对象,使其永远不会转换为 proxy。返回对象本身。

6、pinia-plugin-persistedstate

pinia和vuex都有一个通病,就是数据持久化需要手动修改,插件本身不具备数据持久化的能力,当页面刷新或者应用更新后所有的状态数据均会丢失。

一般来说在vuex中我们的解决发放就是利用缓存去处理,在pinia 中有一个好用的插件可以解决这个问题。

$ yarn add pinia-plugin-persist # 或者npm
$ npm install pinia-plugin-persist
赞(1) 打赏
转载请附上原文出处链接:胖蔡说技术 » Vue新一代的轻量级状态管理Pinia,你了解吗?
分享到: 更多 (0)

请小编喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏