useRequest
该 hook 用于处理请求,包括请求的发送、请求的状态、请求的结果等。
实现源码
ts
import { ref, shallowRef, computed, watch } from 'vue';
import type { Ref, ShallowRef } from 'vue';
export interface IRequestOptions {
defaultPage?: number;
defaultPageSize?: number;
/**
* page或pageSize变化后,是否立即请求数据
*/
immediate?: boolean;
}
export type IRequestFn<T, Q> = (query: Q) => Promise<{ data: T[]; total: number }>;
interface IRequestReturn<Q> {
total: Ref<number>;
loading: Ref<boolean>;
page: Ref<number>;
pageSize: Ref<number>;
lastPage: Ref<number>;
fetchData: (query?: Q) => void;
}
export function useRequest<T, Q extends Record<string, any> = {}>(
request: IRequestFn<T, Q>,
options?: IRequestOptions
): {
list: Ref<T[]>;
} & IRequestReturn<Q>;
export function useRequest<T, Q extends Record<string, any> = {}>(
request: IRequestFn<T, Q>,
options: IRequestOptions,
isShallow: true
): {
list: ShallowRef<T[]>;
} & IRequestReturn<Q>;
export function useRequest<T, Q extends Record<string, any> = {}>(
request: IRequestFn<T, Q>,
{
defaultPage = 1,
defaultPageSize = 10,
immediate = false
}: IRequestOptions = {},
isShallow = false
) {
const list: Ref<T[]> | ShallowRef<T[]> = !isShallow
? ref([])
: shallowRef([]);
const loading = ref(false);
const total = ref(0);
const page = ref(defaultPage);
const pageSize = ref(defaultPageSize);
const lastPage = computed(() => {
if (!total.value || !pageSize.value) {
return 0;
}
return Math.ceil(total.value / pageSize.value);
});
const fetchData = (query?: Q) => {
const params = {
page: page.value,
pageSize: pageSize.value,
...query
} as unknown as Q;
loading.value = true;
request(params)
.then((res) => {
list.value = res.data;
total.value = res.total;
})
.finally(() => {
loading.value = false;
});
};
if (immediate) {
watch(
[page, pageSize],
() => {
fetchData();
},
{ immediate: true }
);
}
return {
list,
total,
loading,
page,
pageSize,
lastPage,
fetchData
};
}介绍
本文 useRequest 可以用来快速创建分页请求。该函数接收三个参数:
request请求函数,返回值为Promise<{ data: T[]; total: number }>;options可选参数,包含三个可选属性:defaultPageSize默认分页大小,默认值为10;defaultPage默认当前页,默认值为1;immediate页码或每页大小变化时是否立即发起请求,默认值为false。
isShallow是否使用shallowRef对 data 进行响应式,默认值为false。
返回值为一个对象,包含以下属性:
list请求结果;total请求结果总数;page当前页码;pageSize每页大小;loading请求状态;lastPage最后一页页码;fetchData发起请求函数;
使用
vue
<template>
<a-table
class="ant-table-striped"
:columns="columns"
:data-source="list"
:loading="loading">
...
</a-table>
<a-pagination
v-model:current="page"
v-model:page-size="pageSize"
:total="total" />
</template>
<script setup>
import { useRequest } from 'useRequest.ts';
const columns = [...];
const { page, pageSize, total, loading, list } = useRequest(
(params: { page: number; pageSize: number; key?: string; }) => {
return new Promise<{ total: number; data: any[] }>((resolve) => {
setTimeout(() => {
resolve({
data: [],
total: 0
})
}, 1000);
})
},
{
immediate: true
}
);
</script>