vue3中封装一个请求hook

2,743 阅读1分钟

通过封装一个请求hook,在我们使用axios发送请求时,直接使用useRequest即可。不用再每发送一次请求写一遍axios请求。

request.ts

import { reactive, toRefs, onMounted, ComputedRef } from "vue";
import axios from "axios";
const defaultConfig = { immediate: true };

function useRequest(args: any) {
  const { url, params = undefined, config = {} } = args;
  const _params = params;
  const combineConfig = { ...defaultConfig, ...config };
  const {
    initData,
    immediate,
    onSuccess,
    onError,
    ...axiosConfig
  } = combineConfig;
  
  // 初始化请求返回值
  const state = reactive({
    loading: false,
    error: false,
    data: initData,
  });
  
  // 请求方法
  const fetchFun = () => {
    state.loading = true;
    const method = "get";
    return axios({
      url: url.value ? url.value : url,
      method,
      params: _params?.value,
      ...axiosConfig,
    })
      .then((response) => {
        const { data } = response;
        if (data.code === 200) {
          state.data = data.data;
          state.loading = false;
          if (typeof onSuccess === "function") {
            onSuccess(data);
          }
        } else {
          if (typeof onError === "function") {
            onError(data);
          }
        }
      })
      .catch((err) => {
        state.error = true;
        state.loading = false;
      });
  };
    
    //生命周期 mounted 发送请求 
  onMounted(() => {
    if (immediate) {
      fetchFun();
    }
  });
  return { ...toRefs(state), fetch: fetchFun };
}

export default useRequest;

demo.vue

<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import useRequest from '@/assets/ts/request'
import { MovieType } from '@/assets/interfaces'

interface InitDataType {
  movie: Partial<MovieType>
  relativeMovies: MovieType[]
}

export default defineComponent({
  setup() {
   const router = useRouter()
    const route = useRoute()
    // 初始化数据
    const initData: InitDataType = { movie: {}, relativeMovies: [] }
    // 请求成功的回调
    const onSuccess = (res: any) => {
      const { movie } = res.data
     // do something
    }
    // 请求url
    const reqUrl = computed(() => `/api/movie/${route.params.id}`)
    // 使用useRequest 发送请求
    const { data, loading, fetch } = useRequest({
      url: reqUrl,
      params: route.params.id,
      config: {
        initData,
        onSuccess
      }
    })

    // 监听路径上的id,变化则发送请求
    watch(
      () => route.params.id,
      () => {
        fetch()
      }
    )
   
   

    return {
     //.....
    }
  }
})
</script>