Loading...
Loading...
Documentation of the project's standardized approach to using `@vueuse/integrations/useAxios`. Focuses on minimizing boilerplate, leveraging global error handling, utilizing built-in state management, and enforcing consistent naming conventions.
npx skill4agent add ztn9709/skills vueuse-axios-conventionsuseAxiostry-catchElMessage.erroraxiosInstancesrc/utils/http.tsElMessage.errortry {
await execute();
} catch (error) {
ElMessage.error("Failed to fetch");
}// Error is handled automatically by http.ts
await execute().catch(() => undefined);executeexecuteDeleteexecuteFetch| Property | Only 1 in component | Multiple in component |
|---|---|---|
| Keep | Rename to content meaning: |
| Keep | Rename to semantic verb: |
| Keep | Rename to scenario: |
const { execute: executeFetch } = useAxios(...)
const { execute: executeDeleteDraft } = useAxios(...)
const { data: detailsData } = useAxios(...)
const { data: dataStatsRes } = useAxios(...)// Single useAxios — no rename needed
const { data, execute, isLoading } = useAxios(...)
// Multiple useAxios — use semantic names
const { data: detail, execute: fetchDetail } = useAxios(...)
const { execute: deleteDraft } = useAxios(...)
const { data: materials, execute: fetchMaterials, isLoading: materialsLoading } = useAxios(...)useAxiosimmediate: trueimmediateundefinedimmediate: trueimmediate: false// Auto-fetch on mount — must declare immediate explicitly since options object is provided
const { data, isLoading } = useAxios<T>("/url", axiosInstance, {
immediate: true,
initialData: { results: [], count: 0 },
});
// Auto-fetch — no options object, immediate defaults to true
const { data } = useAxios<T>("/url", axiosInstance);
// Manual execution — immediate defaults to false when options aren't provided
// because the empty URL signals manual use
const { execute: submitMaterial, isLoading: isSubmitting } = useAxios<T>(
"",
axiosInstance,
);
const { execute: deleteDraft } = useAxios(
"",
{ method: "DELETE" },
axiosInstance,
);isLoadinguseAxiosloadingconst { isLoading: isSubmitting } = useAxios("/url", axiosInstance);
// In template:
// <el-button :loading="isSubmitting">Submit</el-button>initialDatadata?.const { data } = useAxios<PaginatedResponse>("/url", axiosInstance, {
immediate: true,
initialData: { results: [], count: 0 },
});
// In template — no need for data?.results
// <el-table :data="data.results">
// <el-pagination :total="data.count">onSuccessonError// onSuccess — handle side effects after successful request
const { execute: updateFiles } = useAxios<FileUpload[]>(
"/upload/file/update/",
{ method: "POST" },
axiosInstance,
{
onSuccess: (files) => {
ElMessage.success("Upload success!");
categoryRef.value = [...categoryRef.value, ...files];
isDialogVisible.value = false;
},
},
);
// onError — redirect on failure
const { data: detail, execute: fetchDetail } = useAxios<MaterialDetail>(
"",
axiosInstance,
{
onSuccess: ({ expSerial }) => {
/* process data */
},
onError: () => router.push("/"),
},
);execute()StrictUseAxiosReturndataerrordata// ✅ Use return value — avoids needing a separate data ref
const { execute: uploadFile } = useAxios<FileUpload>(
"/upload/file/",
{ method: "POST" },
axiosInstance,
{
abortPrevious: false,
},
);
const handleFileUpload = async ({ file }: UploadRequestOptions) => {
const formData = new FormData();
formData.append("file", file);
const { data } = await uploadFile({ data: formData });
return data.value!;
};
// ✅ Use return value in submit flow
const response = await submitMaterial(url, { method, data }).catch(
() => undefined,
);
if (!response) return;
router.push(`/details/${response.data.value.id}`);onSuccessonErrorimmediateinitialDataabortPreviousheadersmethodurldataparams// 1. Static config at initialization
const { execute: searchImages } = useAxios<Response>(
"/services/",
{ method: "POST" },
axiosInstance,
{
onSuccess: ({ images }) => (serialImages.value = images),
},
);
// 2. Dynamic data at execution time
const onSearch = () =>
searchImages({
data: { filters: JSON.stringify(filterItems.value) },
}).catch(() => undefined);paramsreactivewatchconst params = reactive({ page: 1, pageSize: 10 });
const {
data,
execute: fetchData,
isLoading,
} = useAxios<PaginatedResponse>("/items/", { params }, axiosInstance, {
immediate: true,
initialData: { results: [], count: 0 },
});
// Auto-refetch when params change
watch(params, () => fetchData().catch(() => undefined));const { execute: deleteItem } = useAxios(
"",
{ method: "DELETE" },
axiosInstance,
{
onSuccess: () => {
ElMessage.success("Deleted");
if (data.value.results.length === 1 && params.page > 1) params.page -= 1;
else fetchData().catch(() => undefined);
},
},
);
const handleDelete = async (id: number) => {
try {
await ElMessageBox.confirm("确认删除?", "提示", { type: "warning" });
await deleteItem(`/items/${id}/`);
} catch {
// Only swallow 'cancel'
}
};