vue3 provide 的一种封装使用方式

25 阅读1分钟

useProvide.ts

inject要在子组件才能获取到值,父组件的不同方法/文件引用里无法获取到值

/** @/hooks/useProvide.ts */
import { inject, provide } from 'vue';

import { createSharedComposable } from '@vueuse/core';

export const useProvide = <T extends (...args: any[]) => any>(fn: T, key?: string | symbol) => {
  if (!key) {
    key = Symbol();
  }
  const provideFn = (...args: Parameters<T>) => {
    const result = fn(...args) as ReturnType<T>;
    provide(key, result);
    return result;
  };

  const injectFn = () => {
    return inject(key!, undefined) as ReturnType<T>;
  };

  return [provideFn, injectFn] as const;
};

export const useSharedProvide = <T extends (...args: any[]) => any>(fn: T) => {
  return createSharedComposable(<T extends (...args: any[]) => any>(fn: T) => {
    const Initial = undefined as unknown as ReturnType<T>;
    const resetCallbackFns: (() => void)[] = [];
    const shared = {
      value: Initial,
    };
    const provideFn = (...args: Parameters<T>) => {
      shared.value = fn(...args) as ReturnType<T>;
      return shared.value;
    };

    const injectFn = () => {
      return shared.value;
    };

    const onReset = (callback: () => void) => {
      resetCallbackFns.push(callback);
    };
    // 添加清理方法
    const reset = () => {
      for (const resetCallbackFn of resetCallbackFns) {
        resetCallbackFn();
      }
      shared.value = Initial;
      resetCallbackFns.length = 0;
    };

    return [provideFn, injectFn, reset, onReset] as const;
  })(fn);
};

示例

/** variables.ts */
import { useProvide } from '@/hooks/useProvide.ts';
export const [useDataProvide, useData] = useProvide(() => {
  const { globalData, sendMessage } = useGlobalData();
  const chatList = ref<LiveRoomChatBasicModel[]>([]);
  const initChatData = async () => {
    const res = await getLiveRoomChatService({
      pageNum: 1,
      pageSize: 100,
      params: {
        roomId: globalData.roomId,
      },
    });
    chatList.value = res.data;
  };

  return { chatList, initChatData };
});
/** 父组件.ts */
import { useDataProvide } from './variables';
export const useProps = () => {
  const { chatList, initChatData } = useDataProvide();
  return { chatList, initChatData }
}
/** 子组件.ts */
import { useData } from './variables';
export const useProps = () => {
  const { chatList, initChatData } = useData();
  return { chatList, initChatData }
}