我是靠谱客的博主 轻松哈密瓜,这篇文章主要介绍Vue3状态管理的使用详解,现在分享给大家,希望可以做个参考。

背景

随着Vue3的逐步应用,对状态管理的需求越来越多。起初是基于Vuex4进行状态管理的,但是Vuex4也暴露了一些问题。从个人角度来说,Vuex4类似于过渡期产品,对TypeScript的支持性并不完整。如果使用TypeScript编写组件,需要遵循一定步骤后,才可以正确进行类型推断,并且对modules的使用上也并不友好。Vuex核心贡献者Kia King也表示Vuex5已经在计划中,并且能提供完整的TypeScript支持,那么在Vuex5面世之前,或者直接"舍弃"Vuex的话有没有其他状态管理的方案?

Provide / Inject

provide和inject并不是Vue3的新特性,在Vue2中就已经存在了。文档中提到provide和inject绑定并不是可响应的。然而,如果你传入了一个可监听的对象,那么其对象的property还是可响应的。

Vue3在Computed与watch的基础上新增了响应性API ref和reactive,可以更加方便provide和inject的应用,再结合Composition API的思想,是否能实现一个简易版的状态管理?

抽离共享状态

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// src/context/calculator.ts import { ref, inject, provide, readonly } from 'vue'; type Calculator = { count: number; increase: () => void; updateCount: (num: number) => void; }; //provide的key,唯一令牌 const CalculatorSymbol = Symbol(); //提供者 export const calculatorProvide = () => { //数目 const count = ref<number>(1); //递增方法 const increase = () => { count.value++; }; //更新方法 const updateCount = (num: number) => { count.value = num; }; //提供的共享状态对象 const depends = { count: readonly(count), //状态只读,通过方法进行修改 increase, updateCount }; //使用provide api实现状态对象提供 provide(CalculatorSymbol, depends); //返回状态对象,让同级可调用 return depends; }; //注入方法 export const calculatorInject = () => { //使用inject api注入状态 const calculatorContext = inject<Calculator>(CalculatorSymbol); //未共享就注入的错误校验 if (!calculatorContext) { throw new Error('Inject must be used affer Provide'); } //返回注入的贡献状态 return calculatorContext; };

提供数据

相比起Vuex的全局共享,利用Provide / Inject可以实现全局或者局部共享,

全局共享,可以在main.ts中注入全局状态:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/main.ts import { createApp, h } from 'vue'; import App from '@/App.vue'; import { calculatorProvide } from '@/context/calculator'; // 创建vue实例 const app = createApp({ setup() { calculatorProvide(); return () => h(App); } }); // 挂载实例 app.mount('#app');

如果只想局部共享,可以在父组件中注入状态

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
// src/views/parent.vue import { defineComponent } from "vue"; import { calculatorProvide } from '@/context/calculator'; export default defineComponent({ name: "parent", setup() { //共享数据 calculatorProvide(); } });

注入数据

子组件可以通过状态注入,使用或修改状态

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
// src/views/child.vue import { defineComponent } from "vue"; import { calculatorInject } from '@/context/calculator'; export default defineComponent({ name: "child", setup() { //注入数据 const { count, increase, updateCount } = calculatorInject(); } });

小结

实际上,你可以将依赖注入(Provide / Inject)看作是"long range props",除了:

  • 父组件不需要知道哪些子组件使用它provide的property
  • 子组件不需要知道inject的property来自哪里

Vue3使依赖注入的使用更加灵活便捷,以此仿造了小型的状态管理,个人测试上,对TypeScript的支持性比较完整

reactive

那么不使用Provide / Inject,还有别的方法可以实现状态管理吗?直接上代码。

抽离共享状态

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/context/calculator.ts type Calculator = { count: number; increase: () => void; updateCount: (num: number) => void; }; //共享状态 const calculatorStore = reactive<Calculator>({ count: 1, increase: () => { calculatorStore.count++; }, updateCount: (num: number) => { calculatorStore.count = num; } }); export { calculatorStore };

使用共享状态

使用状态的方法很简单,只需要import状态即可,需要使用状态的组件,都需要导入

复制代码
1
2
3
4
5
6
7
8
9
10
11
// src/views/any.vue import { defineComponent } from "vue"; import { calculatorStore } from '@/context/calculator'; export default defineComponent({ name: "any", setup() { console.log(calculatorStore.count); } });

小结

其实这个方案利用的是reactive的响应性及import同一实例原理,相比起依赖注入来的更简单粗暴,也能正确支持TypeScript校验。但是依赖注入可以在不同根节点共享不同的数据,而这个reactive方案永远共享的是一个实例,在某些业务场景下并不适用。

结语

首先,Vuex仍旧是更成熟全面的方案,只是针对一些简单的状态管理,可以尝试换个思路解决;当然以上的方案可能还有很多考虑不全地方,欢迎各位大神指点指点~

以上就是Vue3状态管理的使用详解的详细内容,更多关于Vue3状态管理的使用的资料请关注靠谱客其它相关文章!

最后

以上就是轻松哈密瓜最近收集整理的关于Vue3状态管理的使用详解的全部内容,更多相关Vue3状态管理内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(187)

评论列表共有 0 条评论

立即
投稿
返回
顶部