最近在学习nuxt3,在数据获取上,官方文档推荐使用useFetch,琢磨了一下,通过以前封装axios的经验,利用class封装了useFetch
useFetch 参数类型
function useFetch(
url: string | Request | Ref<string | Request> | () => string | Request,
options?: UseFetchOptions<DataT>
): Promise<AsyncData<DataT>>
type UseFetchOptions = {
key?: string
method?: string
query?: SearchParams
params?: SearchParams
body?: RequestInit['body'] | Record<string, any>
headers?: Record<string, string> | [key: string, value: string][] | Headers
baseURL?: string
server?: boolean
lazy?: boolean
immediate?: boolean
default?: () => DataT
transform?: (input: DataT) => DataT
pick?: string[]
watch?: WatchSource[]
}
type AsyncData<DataT, ErrorT> = {
data: Ref<DataT | null>
pending: Ref<boolean>
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
error: Ref<ErrorT | null>
}
interface AsyncDataExecuteOptions {
dedupe?: boolean
}
完整封装代码
import type { AsyncData, UseFetchOptions } from 'nuxt/dist/app/composables'
type Methods = 'GET' | 'POST' | 'DELETE'
export interface IResultData<T> {
code: number
data: T
}
export interface IInterceptor extends
Pick<UseFetchOptions<any>, 'onRequest' | 'onRequestError' | 'onResponse' | 'onResponseError'> {}
export interface IConfig {
baseURL: any
interceptor?: IInterceptor
}
export interface IOption<T> {
url: string
method?: Methods
query?: any // query -> params
body?: any
options?: UseFetchOptions<T>
}
class Request {
public baseURL: string
public interceptor: IInterceptor
constructor({ baseURL, interceptor }: IConfig) {
this.baseURL = baseURL
this.interceptor = interceptor as IInterceptor
}
request<T = any>({ url, method, query, body, options }: IOption<T>): Promise<AsyncData<T, Error>> {
return new Promise((resolve, reject) => {
const newOptions: UseFetchOptions<T> = {
baseURL: this.baseURL,
method,
query,
body,
...options,
onRequest: this.interceptor?.onRequest,
onRequestError: this.interceptor?.onRequestError,
onResponse: this.interceptor?.onResponse,
onResponseError: this.interceptor?.onResponseError
}
useFetch<T>(url, newOptions as any)
.then((res) => {
// res => { data:T, pending, refresh, error ... } => AsyncData
resolve(res as AsyncData<T, Error>)
})
.catch((error) => {
reject(error)
})
})
}
get<T = any>({ url, query, options }: IOption<T>) {
return this.request<T>({ url, method: 'GET', query, options })
}
post<T = any>({ url, body, options }: IOption<T>) {
return this.request<T>({ url, method: 'POST', body, options })
}
delete<T = any>({ url, query, options }: IOption<T>) {
return this.request<T>({ url, method: 'DELETE', query, options })
}
}
export default Request
使用
import Request from './request'
import { LOGIN_TOKEN } from '@/global/constants'
import { cookieCache } from '@/utils/cache'
import 'element-plus/es/components/message/style/css'
const request = new Request({
baseURL: import.meta.env.VITE_BASE_URL,
interceptor: {
// 请求成功拦截
onRequest: ({ options }) => {
const token = cookieCache.getCache(LOGIN_TOKEN)
if (token) {
options.headers = (options.headers as { [key: string]: string }) || ({} as { [key: string]: string })
options.headers.authorization = token
}
},
// 响应成功拦截
onResponse({ response }) {
const { code, message } = response._data
}
}
})
export { request }
希望能帮助到大家