在 Vue 3 中,组合式 API(Composition API)为我们提供了更灵活的方式来组织代码。今天,我们将实现一个通用的 useMutate Hook,用于处理数据请求并更新组件中的数据状态。这个 Hook 将帮助我们封装数据获取、格式化、状态管理等逻辑,从而使得组件更简洁且易于复用。
背景
在前端开发中,数据的请求和展示是常见的功能。为了避免在每个组件中重复相似的代码,我们可以将数据请求的逻辑抽象成一个可复用的 Hook。useMutate Hook 的目标就是封装数据请求、处理无数据状态和格式化数据的逻辑,帮助我们简化代码并提高开发效率。
需求分析
我们需要实现以下功能:
1. 数据请求: 向服务器请求数据。
2. 数据格式化: 支持自定义的数据格式化函数。
3. 请求成功回调: 请求成功后触发回调,方便后续操作。
4. 无数据状态管理: 判断返回数据是否为空,并更新 noData 状态。
代码实现
下面是我们实现的 useMutate Hook:
import { onMounted, ref } from 'vue';
import { useLockFn } from './useLockFn';
interface IMutateOption<T> {
/** 默认数据 */
defaultData?: T;
/** 额外传递参数 */
params?: Record<string, any>;
/** 初始是否发出请求 */
initRequest?: boolean;
/** 获取数据 */
getData: (data: Record<string, any>) => Promise<{ data?: T }>;
/** 数据格式化 */
dataFormat?(data?: T): any;
/** 请求成功后的回调 */
successCallback?(data?: T): void;
}
export function useMutate<T>(config: IMutateOption<T>) {
const { defaultData, params, initRequest = true } = config;
const detail = ref<T | undefined>(defaultData);
const noData = ref<boolean>();
const isInit = ref(initRequest);
const mutate = useLockFn(async () => {
try {
const { data } = await config.getData({ ...params });
const newData = config.dataFormat ? config.dataFormat(data) : data;
detail.value = newData;
config?.successCallback?.(newData);
/**暂无数据 */
let blo = false;
if (newData !== undefined) {
if (newData instanceof Array) {
blo = newData.length === 0;
} else if (newData instanceof Object) {
blo = Object.keys(newData).length === 0;
}
} else {
blo = true;
}
noData.value = blo;
} catch (error) {
console.log(error);
noData.value = true;
}
}, 500);
onMounted(() => {
if (!isInit.value) {
isInit.value = true;
} else {
mutate();
}
});
return { mutate, detail, noData };
}
使用示例
const { detail, mutate, noData } = useMutate({
getData: () => api['/wechat/api/outWorkOrder/express/{id}_GET'](1),
});
