(必看!!)一文对比Vuex 与 Pinia 的设计实现

lxf2023-03-14 20:00:02

在进行前端项目开发时,状态管理始终是一个绕不开的话题,Vue 与 React 框架本身提供了一部分能力去解决这个问题。但是在开发大型应用时往往有其他考虑,比如需要更规范更完善的操作日志、集成在开发者工具中的时间旅行能力、服务端渲染等。本文以 Vue 框架为例,介绍 Vuex 与 Pinia 这两种状态管理工具在设计与实现上的区别。

Vue 状态管理

首先,先介绍一下 Vue 框架自身提供的状态管理的方式

Vue 组件内主要涉及到状态、动作和视图三个组成部分。

在选项式 API 中通过 data 方法返回一个状态对象,通过 methods 方法设置修改状态的动作。

如果使用组合式 API + setup 语法糖,则是通过 reactive 方法生成状态,而动作只需要当做普通函数或者箭头函数进行定义即可。

选项式 API:

<script>
export default {
  data() {  // 状态 state
    return {
      count: 0
    }
  },
  methods() { // 动作 action
    increment() {
      this.count++
    }
  }
}
</script>
// 视图 view
<template> {{ count }} </template>

组合式 API + setup 语法糖:

<script setup lang="ts">
import { reactive } from 'Vue'
// 状态 state
const state = reactive({
  count: 0
})
// 动作 action
const increment = () => {
  state.count++
}
</script>
// 视图 view
<template> {{ state.count }} </template>

(必看!!)一文对比Vuex 与 Pinia 的设计实现

视图由状态生成,操作可以修改状态。

如果可以将页面的某一部分单独抽离成与外界解耦的状态、视图、动作组成的独立个体,那么 Vue 提供的组件内的状态管理方式已经足够了。

但是开发中经常会遇到这两种情况:

  • 多个页面组件依赖于相同的状态。
  • 在多个页面组件内的不同交互行为需要修改同一个状态。

比如我们要做一个主题定制功能,需要在项目入口处获取接口中的颜色参数,然后在整个项目的很多页面都要使用到这个数据。

一种方法是使用 CSS 变量,在页面的最顶层的 root 元素上定义一些 CSS 变量,在 Sass 中使用 var() 初始化一个 Sass 变量,所有页面都引用这个变量即可。在项目入口处获取接口数据,需要手动去修改 root 元素上的 css 变量。

在 Vue 中,框架提供了一种 v-bind 的方式去编写 css,我们可以考虑将所有颜色配置存放在一个统一的 store 里面。

遇到这两种情况,通常我们会通过组件间通信的方式解决,比如:

  • 对于相邻的父子组件:props/emit
    • defineProps({})
    • defineEmits(['change', '...'])
  • 对于多层级嵌套:provide/inject
    • provide(name: string | symbol, value: any)
    • inject(name: string | symbol, defaultValue: any)

1、如果是相邻的父子组件之间通信,可以通过 props+emit 的方式,父组件通过子组件的 props 传入数据,在子组件内部通过 emit 方法触发父组件的一些方法。

(必看!!)一文对比Vuex 与 Pinia 的设计实现

2、如果不是直接相邻,而是中间相隔很多层的嵌套关系,那么可以使用 provide+inject 的方式,高层级的组件抛出状态和动作,低层级的组件接收使用数据和触发动作。

(必看!!)一文对比Vuex 与 Pinia 的设计实现

如果目标的两个组件并不在同一条组件链上,一种可能的解决方法是「状态提升」。

可以把共同的状态存储在二者的最小公共祖先组件上,然后再通过上述两种方式进行通信。

  • 前者:公共祖先组件存储状态,通过 props 逐级传递响应式状态以及其关联的操作到子组件。
  • 后者:公共祖先作为提供方,多个后代组件作为注入方获取数据以及操作数据。

后者编写代码更简洁,更不容易出错。

这样已经能够解决大多数场景的问题了,那么在框架之外的状态管理工具,到底能提供哪些与众不同的能力?

Vuex 与 Pinia 核心思想与用法

Flux 架构

Flux 是 Facebook 在构建大型 Web 应用程序时为了解决数据一致性问题而设计出的一种架构,它是一种描述状态管理的设计模式。绝大多数前端领域的状态管理工具都遵循这种架构,或者以它为参考原型。

Flux 架构主要有四个组成部分: