vue3.0自定义hook示例——useGetData
2020, Dec 08
该hook是用于方便发送请求的。
import { reactive, onMounted, Ref, toRef, toRaw, ref, UnwrapRef, readonly, DeepReadonly } from 'vue';
// import { IRes } from '@/utils/axios';
export interface IRes<T> {
status: number;
data: T;
message?: string;
errorMsg?: string;
}
interface UseGetDataOption<T> {
init?: boolean // 是否需要默认请求一次
requestConditions?: (data: T) => Boolean // 请求必须满足怎样的条件
}
export interface UseGetDataReturnData<REQUEST_DATA, DATA_PROPS> {
clearData: () => void // 清除数据
getData: () => Promise<IRes<DATA_PROPS>> // 获取数据
changeRequestData: (requestData: Partial<REQUEST_DATA>) => void; // 修改请求参数
requestLoading: Ref<boolean>; // 请求的loading
data: Ref<UnwrapRef<DATA_PROPS> | null>; // 该请求返回的数据
responseInfo: Ref<IRes<DATA_PROPS>>;// 该请求的返回的全部信息
readonly requestData: DeepReadonly<UnwrapRef<REQUEST_DATA>> // 返回只读的请求数据
}
function useGetData<REQUEST_DATA, DATA_PROPS>(request: (data: REQUEST_DATA) => Promise<IRes<DATA_PROPS>>, requestData: REQUEST_DATA, option: UseGetDataOption<UnwrapRef<REQUEST_DATA>> = { init: true }): UseGetDataReturnData<REQUEST_DATA, DATA_PROPS> {
const state = reactive<{
requestLoading: boolean,
data: DATA_PROPS | null,
responseInfo: IRes<DATA_PROPS> | null,
localRequestData: REQUEST_DATA
}>({
requestLoading: false,
data: null,
responseInfo: null,
localRequestData: requestData
})
const requestLoading = toRef(state, "requestLoading");
const data = toRef(state, "data");
const responseInfo = toRef(state, "responseInfo");
const localRequestData = toRef(state, "localRequestData");
const getData = async () => {
try {
if (option.requestConditions && !option.requestConditions(localRequestData.value)) {
console.log("不满足requestConditions")
return Promise.reject({
errorMsg: "请检查请求参数",
message: "请检查请求参数",
})
}
requestLoading.value = true
const res = await request(localRequestData.value as REQUEST_DATA)
data.value = res.data === null ? null : ref(res.data).value
responseInfo.value = res === null ? null : ref(res).value
requestLoading.value = false
return Promise.resolve(res)
} catch (e) {
responseInfo.value = e.errorMsg ? e : null
data.value = e.errorMsg ? e.data : null
requestLoading.value = false
return Promise.reject(e)
}
}
const changeRequestData = async (newRequestData: Partial<REQUEST_DATA>) => {
localRequestData.value = ref(Object.assign(toRaw(localRequestData.value), newRequestData)).value
}
const clearData = async () => {
data.value = null
responseInfo.value = null
}
const initUse = () => {
if (!option.init) return
getData()
}
onMounted(() => initUse())
return {
requestLoading,
data,
responseInfo,
requestData: readonly(localRequestData).value,
changeRequestData,
clearData,
getData,
}
}
export default useGetData;
使用方式
// 获取数据的axios封装
// service.ts
export async function getData(data: RequestData) {
return await http.request<DataProps[]>(axios)
}
// data.ts
interface StateProps{
requestData: UseGetDataReturnData<RequestTimetableData, TimeTableData>; // 类型定义
}
// 初始化这个hook
const requestData = useGetData(getData,
{
// 请求参数
},
{
init: false,
}
), // 请求数据
// 修改请求参数
requestData.value.changeRequestData({
// 需要修改的字段
})
// 请求数据
requestData.value.getData()