Vue3状态管理的使用详解

2022-04-15 0 347
目录
  • 背景
  • Provide / Inject
    • 抽离共享状态
    • 提供数据
    • 注入数据
    • 小结
  • reactive
    • 抽离共享状态
    • 使用共享状态
    • 小结
  • 结语

    背景

    随着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的思想,是否能实现一个简易版的状态管理?

    Vue3状态管理的使用详解

    抽离共享状态

    // 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中注入全局状态:

    // 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');
    

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

    // src/views/parent.vue
    
    import { defineComponent } from "vue";
    import { calculatorProvide } from '@/context/calculator';
    
    export default defineComponent({
      name: "parent",
      setup() {
        //共享数据
        calculatorProvide();
      }
    });
    

    注入数据

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

    // 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,还有别的方法可以实现状态管理吗?直接上代码。

    抽离共享状态

    // 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状态即可,需要使用状态的组件,都需要导入

    // 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状态管理的使用的资料请关注NICE源码其它相关文章!

    免责声明:
    1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

    2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
    如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
    如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

    NICE源码网 JavaScript Vue3状态管理的使用详解 https://www.niceym.com/34015.html