vue3的hooks+ts体验

496 阅读1分钟

1. element-plus的loading二次封装

// useLoading.ts(promise版本)
import { reactive } from 'vue';
import { ElLoading } from 'element-plus'
import "element-plus/theme-chalk/el-loading.css";


const useLoading = <T = any>(fn: (args: any) => Promise<T>, options?: Parameters<typeof ElLoading.service>[0]) => {
  const loadingInstance = reactive({data: {close: () => undefined}})

  const openLoading = (options?: Parameters<typeof ElLoading.service>[0]) => {
    loadingInstance.data = ElLoading.service({fullscreen: true, background: "#4c4c4c",text: "loading...",...options}) as any
  }

  const closeLoading = () => loadingInstance?.data?.close()

  return  (args?: any) =>
    new Promise(async (resolve, reject) => {
      openLoading(options)
      let res = await fn(args)
      resolve(res)
    }).catch(err => {
      console.log(err);
    }).finally(closeLoading())
}

export default useLoading





// hook回调版本
// const useLoading = () => {
//   const loadingInstance = reactive({data: { close: () => ''}})

//   const openLoading = (options?: any) => loadingInstance.data = ElLoading.service({fullscreen: true, background: "#4c4c4c",
//   text: "loading...",...options}) as any
//   const closeLoading = () => loadingInstance?.data?.close()
//   return {
//     closeLoading,
//     openLoading
//   }
// }
// export default useLoading

2. 省/城市/行政区联动

import { computed, ref, reactive } from "vue";

import type {
  IProvinceCityRegionRequestType,
  IFormAreaDataType
} from "@/views/resource/business/config/type";


import type {
  IProvinceAndCityRoot,
  IProvinceAndCityAndRegion
} from "@/service/common/type";

import { queryProvinceAndCityAndRegionApi } from "@/service/common/index";

import { isArray, isObject } from "@/utils/index";

enum QueryTypeEnum {
  QUERY_PROVINCE = "QUERY_PROVINCE",
  QUERY_CITY = "QUERY_CITY",
  QUERY_REGION = "QUERY_REGION"
}

const useHandleArea = () => {
  const currentProvince = reactive<{ data: IProvinceAndCityAndRegion }>({
    data: { id: "", name: "", parentId: "" }
  });
  const currentCity = reactive<{ data: IProvinceAndCityAndRegion }>({
    data: { id: "", name: "", parentId: "" }
  });
  const currentRegion = reactive<{ data: IProvinceAndCityAndRegion }>({
    data: { id: "", name: "", parentId: "" }
  });

  const areaMap = reactive<Map<QueryTypeEnum, IProvinceAndCityAndRegion[]>>(
    new Map()
  );
  const queryProvinceAndCityAndRegion = async (
    data: IProvinceCityRegionRequestType,
    type: QueryTypeEnum
  ) => {
    try {
      const res: IProvinceAndCityRoot<any> =
        await queryProvinceAndCityAndRegionApi({ data });
      const resData: IProvinceAndCityAndRegion[] = res?.data;
      handleProvinceAndCityAndRegion(type, resData);
    } catch (error) {
      console.log(error);
    }
  };

  const handleProvinceAndCityAndRegion = (
    type: QueryTypeEnum,
    resData: IProvinceAndCityAndRegion[]
  ) => areaMap.set(type, [...resData]);

  const changeSelectProvince = (value: IProvinceAndCityAndRegion) => {
    currentProvince.data = value;
  };

  const changeSelectCity = (value: IProvinceAndCityAndRegion) =>
    (currentCity.data = value);

  const changeSelectRegion = (value: IProvinceAndCityAndRegion) =>
    (currentRegion.data = value);

  const clearCache = () => {
    areaMap.forEach((value, key) => {
      if (key !== QueryTypeEnum.QUERY_PROVINCE) {
        areaMap.set(key, []);
      }
    });
    changeSelectProvince({ id: "", name: "", parentId: "" });
    changeSelectCity({ id: "", name: "", parentId: "" });
    changeSelectRegion({ id: "", name: "", parentId: "" });
  };

  const handleProvinceOpen = async () => {
    if (
      isArray(
        areaMap.get(QueryTypeEnum.QUERY_PROVINCE) as IProvinceAndCityAndRegion[]
      )
    )
      return clearCache();
    await queryProvinceAndCityAndRegion(
      { name: "", parentId: "" },
      QueryTypeEnum.QUERY_PROVINCE
    );
    clearCache();
  };

  const handleCityOpen = async () => {
    if (!currentProvince?.data?.id) return;
    await queryProvinceAndCityAndRegion(
      { name: "", parentId: currentProvince?.data?.id },
      QueryTypeEnum.QUERY_CITY
    );
  };

  const handleRegionOpen = async () => {
    if (!currentCity?.data?.id) return;
    await queryProvinceAndCityAndRegion(
      { name: "", parentId: currentCity?.data?.id },
      QueryTypeEnum.QUERY_REGION
    );
  };

  const handleSelectOpen = async (type: QueryTypeEnum) => {
    switch (type) {
      case QueryTypeEnum.QUERY_PROVINCE:
        await handleProvinceOpen();
        break;
      case QueryTypeEnum.QUERY_CITY:
        await handleCityOpen();
        break;
      case QueryTypeEnum.QUERY_REGION:
        await handleRegionOpen();
        break;
    }
  };
  const handleSelectClose = (type: QueryTypeEnum) => {};

  const visibleChange = async (value: boolean, type: QueryTypeEnum) =>
    value ? await handleSelectOpen(type) : handleSelectClose(type);

  return {
    QueryTypeEnum,
    areaMap,
    currentProvince,
    currentCity,
    currentRegion,
    clearCache,
    visibleChange,
    changeSelectProvince,
    changeSelectCity,
    changeSelectRegion
  };
};

export default useHandleArea;