typescript vuex_Vue 3 带来的 Vuex 的替代方案

一、前言

就像是 React 社区在 HOOK API 出现后很快就使用 useReducer、useContext 代替了 Redux 进行状态管理一样。Vue3 也是时候抛弃 Vuex 进行状态管理了。

在考虑为什么要抛弃 Vuex 之前,我们先来想一下为什么要引入 Vuex?

Vuex 实际上解决的问题是「组件间传递对象」的问题:

在传统的方式里,我们如果要把一个对象从父组件传递到子组件,要使用 prop 进行传递。

如果组件间不是直接的「父子关系」的话(如「爷孙关系」),传递对象的过程要经过整颗组件树————这让我们的代码变得很丑陋,提高了相当多的复杂度。

我们引入 Vuex 就是为了提供一个统一管理组件状态的地方,来让我们的组件之间可以简单的传递对象。

但是引入 Vuex 的本质原因还是:降低代码的复杂度

但是 Vuex 陡峭的学习曲线,令人费解的 Getter、Module、Store、Mutation、Action 等概念,又引入了新的代码复杂度,新的心智负担。

当我真正掌握了它的时候,我并没有惊呼,而是对其产生了深深的排斥。

所以,当现在 Vue3 到来,有了更新、更轻量的依赖注入工具 provide、inject 函数,我们有什么道理不像隔壁的 React 社区学习————用 useReducer、useContext (provide、inject)代替 Redux(Vuex)呢?


二、关于 Vue3 与 Vue Composition API

目前 Vue 3 还处于 Alpha 版本,但是我们已经可以通过使用 @vue-composition 来提前在 Vue2 环境下体验 Vue3 的新特性了。

  • vue 3 的 Github:https://github.com/vuejs/vue-next
  • vue-composition 的 Github:https://github.com/vuejs/composition-api
  • vue-composition 的使用文档:https://vue-composition-api-rfc.netlify.com/api.html

vue-composition 提供了类似 React Hook 的能力,将 Vue 的抽象层级从「组件级(Component)」降低为「函数级(Function)」。

用了将近一周的时间,说句实话,我感觉到非常的兴奋!

Vue Composition API 的建议学习路线

如果想学习 vue-composition 的同学,可以点击上面的 vue-composition 的使用文档进行学习,学习路线建议如下:

  1. 在 vue2.0 项目中安装 composition-api(请查看 composition-api 的Github)
  2. 学习 composition-api 的 API Reference 文档
  3. 在 vue2.0 项目中使用 composition-api + typescript 重构(推荐使用 typescript 的原因是,都 2020 年了)
  4. 学习 composition-api 的 RFC 文档

三、Vuex 是什么?

打开 Vuex 的官方网站,我们可以看到这样一段描述:

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到了 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

我们来画一下重点,看看 Vuex 提供了什么能力:

  1. 集中式存储管理应用的「所有组件」的「状态」
  2. 保证状态以「可预测」的方式「发生变化」
  3. 与调试工具集成,提供功能:time-travel、状态快照导入导出

我们仔细的看一下,然后准备去设计一个新的状态管理模式

第一条:集中式存储管理「所有组件」的「状态」

请注意,这里它并不是要去管理「所有组件」的「所有状态」———— 也就是说我们每个组件中还是可以有自己的「私有状态」的。

这很好理解:
比如在「登录注册页面」中我们的「短信验证码计时器」的状态很明显就是一个「私有状态」。

那我们要解决的就是集中式存储管理这件事情了,我认为该难点在于:

  1. 需要维护「公共状态」的「单例」性(由于 Chrome 使用的是「标记清除」的垃圾回收策略,而不是「引用计数」的垃圾回收策略,所以我们不用担心在 Vue 的生命周期内变量被 GC 回收的问题)
  2. 需要维护「公共状态」的「命名」全局可见
  3. 需要维护「公共状态」全局可「访问」

第二条:保证状态以「可预测」的方式「发生变化」

需要解决的难点就是,状态的变化可以被追溯到:

即:「哪个组件」改变了「什么状态」

第三条:时间旅行与状态快照导入导出

本条的难点在于——是否全局状态就是一个 Vue APP 的快照?

以及是否有一个工具配合你做调试。


四、provide、inject 是什么?

provide、inject 是 vue-composition-api 的一个新功能:依赖注入功能

import 

这是怎么注入的呢?我们还是看图来说话:

1a29f035a8600a6eea4789bd3373a6e1.png

我们都知道 Vue 是一颗「组件树」,我们只要保证是「父节点」 provide,那么它的「子节点」就一定可以通过 inject 获取到。

举例:

  • A provide,B 可以 inject,C 可以 inject,D 可以 inject
  • B provide,D 可以 inject
  • D provide,没有其它节点可以 inject
  • C provide,没有其它节点可以 inject

五、我们结合一下 Vuex 的特点和 provide、inject 的特性来看,新的状态管理应该具有哪些特点

5.1 声明一次,全局可访问

为了实现这样子的特点,我们就需要将「需要共享的状态」事先在我们 Vue 的根节点 App.vue 中通过 provide 声明好了。

而「单例」的需求也在这里得到解决——我们的状态不会被创建多次。

5.2 全局可访问「公共状态」的「命名」

全局可访问即全局可导入,我们仅需要把「公共状态」的「命名」放在一个单一的文件中即可:

// src/store/store.ts

然后再在需要访问的地方导入:比如 App.vue 中 provide

// src/App.vue

比如 Plan.vue 中 inject(Plan.vue 是 App.vue 的子节点)

// src/views/Plan.vue

5.3 保证「状态」以可预测的方式发生变化

其实.....就是要多设置一个 setter 而已。

就像是 Vuex 中 Store 中存储的状态要靠 mutation 提交才可以更改。

但是这真的有用吗?不是脱了裤子放屁吗?

反正我认为是多此一举,还不如就是直接修改全局变量的状态。

5.4 时间旅行与应用快照

这点需要调试工具配合,目前来看是无法用 inject、provide 替代了。

六、参考文献

https://blog.logrocket.com/use-hooks-and-context-not-react-and-redux/​blog.logrocket.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值