• home > webfront > ECMAS > vue3 >

    vue2升级vue3:vue3真的需要vuex或者Pinia吗?hooks全有了

    Author:zhoulujun Date:

    在写《vue2升级vue3:TypeScript下vuex-module-decorators vuex-class to vuex4 x》,建议新项目使用Pinia,但是我的项目部分组件希望直

    在写 《vue2升级vue3:TypeScript下vuex-module-decorators/vuex-class to vuex4.x》,建议新项目使用 Pinia,但是我的项目部分组件希望直接打包出去给地方使用。这个时候还是会遇到vue2 是否打包出vuex的 问题。所以,干脆舍弃 vuex/Pinia,直接使用 vue3 原生搞定——hook出现之后,状态管理的问题已经从根本上被消解了!

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

    当掌握了Hook(或者Composition API)之后,感觉万物皆可hook,总是想把数据和操作这堆数据的方法封装在一起!


    1、方案有以下几种reactive 响应式数据取代store,在各个组件hooks 调用

    const store = reactive({state: {})

    2、利用rovide和inject,类似react  context,做全局数据管理(不推荐)具体可参看:《vue2升级vue3:provide与inject 使用注意事项

    父组件

    const person = reactive({name: 'bob', age:32});
    provide('person', person);

    子组件

    const person = inject('person');

    有了provide/inject和ref/reactive配合,父子组件/兄弟组件共享状态的问题已经迎刃而解。

    通过provide提供了一个reactive响应式对象;然后在子组件通过inject注入该对象。在子组件修改对象的age属性,视图就会响应式更新!同样的,如果child组件也有自己的子组件,调用inject同样有效。具体参看:


    1、2方法结合:

    hooks

    export function useUserInfo() {
      const userInfo = reactive({ });
      
      const login = (data) => {...};
      const logout = () => {...};
      const editUserInfo => (data) => {};
      
      return {
       userInfo,
       login,
       logout,
       editUserInfo
      }
    }

    在根组件调用provide,将userHook函数传入

    import {useUserInfo} from '@/hooks/userUserInfo';
    provide('user', useUserInfo())

    这个 封装好的东西,直接看这个:https://github.com/tbhuabi/vue-di-plugin

    但是还是不推荐这个写法!即使 provide/inject 再香,我还是绕道走,总感觉 这玩意和react的 useContext + useReducer 貌似 貌合神离——可以看一下  :https://github.com/tangxiangmin/vue3-hook/tree/master/src/useReducer




    1、使用

    比如我之前的数据,vuex的

    /**
     * 面板查询变量
     */
    
    import { VuexModule, Module, getModule, Mutation } from 'vuex-module-decorators';
    import store from '../index';
    import { TimeRangeType } from '@/components/time-range';
    import { DEFAULT_TIME_RANGE, TimeRange } from '@/components/time-range/utils';
    import { FiltersList, FilterType, QueryContextState } from '@/typings';
    
    @Module({ dynamic: true, store, name: 'queryContext' })
    export default class QueryContext extends VuexModule implements QueryContextState {
      timeRange: TimeRangeType = DEFAULT_TIME_RANGE;
      timezone = 'Asia/Shanghai';
      variables: FiltersList = {};
      share_uid = '';
      // 缓存的时间 - TimeRangeType 转时间戳
      get getTimeRange(): [number | string, number | string] {
        const date = new TimeRange(this.timeRange);
        const [start, last] = date.value;
        return [start.valueOf(), last.valueOf()];
      }
      @Mutation
      setTimeRange(range: TimeRangeType) {
        this.timeRange = range;
      }
      @Mutation
      setTimezone(zone: string) {
        this.timezone = zone;
      }
      @Mutation
      setShareUid(share_uid: string) {
        this.share_uid = share_uid;
      }
      @Mutation
      setVariation({ name, value }: { name: string; value: FilterType }) {
        // this.variables[name] = value;
        this.variables = { ...this.variables, [name]: value };
      }
    
      @Mutation
      setVariations(variables: FiltersList) {
        this.variables = variables;
      }
      @Mutation
      clear() {
        this.variables = {};
        this.timeRange = DEFAULT_TIME_RANGE;
      }
    }
    
    export const QueryContextModule = getModule(QueryContext);

    直接使用响应式数据

    import { reactive } from 'vue';
    import { FiltersList, FilterType, QueryContextState } from '@/typings';
    import { DEFAULT_TIME_RANGE } from '@/components/time-range/utils';
    import { TimeRangeType } from '@/components/time-range';
    export const QueryContextModule = reactive<QueryContextState>({
      timeRange: DEFAULT_TIME_RANGE,
      timezone: 'Asia/Shanghai',
      variables: {},
      share_uid: '',
    });
    export function setTimeRange(range: TimeRangeType) {
      QueryContextModule.timeRange = range;
    }
    export function setTimezone(zone: string) {
      QueryContextModule.timezone = zone;
    }
    export function setShareUid(share_uid: string) {
      QueryContextModule.share_uid = share_uid;
    }
    export function setVariation({ name, value }: { name: string; value: FilterType }) {
      QueryContextModule.variables = { ...QueryContextModule.variables, [name]: value };
    }
    export function setVariations(variables: FiltersList) {
      QueryContextModule.variables = variables;
    }
    export function clear() {
      QueryContextModule.variables = {};
      QueryContextModule.timeRange = DEFAULT_TIME_RANGE;
    }

    改为类vuex,可以参看此篇文章: Vue3 还要啥 Vuex,自定义 hooks给你实现数据共享和状态管理 https://juejin.cn/post/7054060160045547550

    import { reactive } from 'vue';
    import { FiltersList, FilterType } from '@/typings';
    import { DEFAULT_TIME_RANGE } from '@/components/time-range/utils';
    import { TimeRangeType } from '@/components/time-range';
    const store = reactive({
      state: {
        timeRange: DEFAULT_TIME_RANGE,
        timezone: 'Asia/Shanghai',
        variables: {},
        share_uid: '',
      },
    });
    
    export function setTimeRange(range: TimeRangeType) {
      store.state.timeRange = range;
    }
    export function setTimezone(zone: string) {
      store.state.timezone = zone;
    }
    export function setShareUid(share_uid: string) {
      store.state.share_uid = share_uid;
    }
    export function setVariation({ name, value }: { name: string; value: FilterType }) {
      store.state.variables = { ...store.state.variables, [name]: value };
    }
    export function setVariations(variables: FiltersList) {
      store.state.variables = variables;
    }
    export function clear() {
      store.state.variables = {};
      store.state.timeRange = DEFAULT_TIME_RANGE;
    }
    
    export const useQueryContext = () => ({
      store,
      setTimeRange,
      setTimezone,
      setShareUid,
      setVariation,
      setVariations,
      clear,
    });


    这个使用肯定是还太粗糙,项目中使用的代码,等有空的 脱密了在分享一下


    参考文章:

    有了 Vue3 还要啥 Vuex,自定义 hooks给你实现数据共享和状态管理 https://juejin.cn/post/7054060160045547550



    转载本站文章《vue2升级vue3:vue3真的需要vuex或者Pinia吗?hooks全有了》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue3/8881.html