本篇专栏基于笔者的Vue专栏,Nuxt3系列,如有不连贯之处可查看Nuxt3系列其他文章!特此说明
一、初始化项目
npx nuxi init <project-name>
cd <project-name>
npm install
npm run dev
如果遇到npx nuxi init 失败,则先按照如下设置,如果不行的话,参考下图链接
二、调整项目结构
api/
---- 用于存放接口相关内容assets/
----- 需要参加打包的静态资源components/
-----组件composables/
------ 可复用逻辑(hooks, mixins)config/
------ 配置layouts/
------ 页面布局middleware/
------ 中间件pages/
------ 页面plugins/
------ 插件public/
------ 不需要参与打包的静态资源server/
------ 服务store/
------ 全局状态types/
------- 自定义类型
三、封装请求接口
这里仅作举例,请根据实际情况进行配置
composables/useHttp.ts
import type { UseFetchOptions } from '#app';
import type { FetchResponse } from 'ofetch';
export interface Response<T> {
data?: T
code?: number
message?: string
success?: boolean
}
export type HttpOption<T> = UseFetchOptions<Response<T>>;
const handleError = <T>(response: FetchResponse<Response<T>> & FetchResponse<ResponseType>) => {
const err = (text: string) => {
// Message.error({
// content: response?._data?.message ?? text,
// icon: () => h(IconEmoticonDead),
// })
}
if (!response._data) {
err('请求超时,服务器无响应!')
return
}
// const userStore = useUserStore()
const handleMap: { [key: number]: () => void } = {
404: () => err('服务器资源不存在'),
500: () => err('服务器内部错误'),
403: () => err('没有权限访问该资源'),
401: () => {
err('登录状态已过期,需要重新登录')
// userStore.clearUserInfo()
navigateTo('/login')
},
}
handleMap[response.status] ? handleMap[response.status]() : err('未知错误!')
}
const fetch = <T>(url: string, option: UseFetchOptions<Response<T>>) => {
return useFetch<Response<T>>(`/api/${url}`, {
// 请求拦截器
onRequest({ options }) {
// 添加请求头,没登录不携带token
// const userStore = useUserStore()
// if (!userStore.isLogin) {
// return
// }
// options.headers = new Headers(options.headers)
// options.headers.set('Authorization', `Bearer ${userStore.getToken}`)
},
// 响应拦截
onResponse({ response }) {
if (response.headers.get('content-disposition') && response.status === 200)
return response
// 在这里判断错误
if (response._data.code !== 200) {
handleError<T>(response)
return Promise.reject(response._data)
}
// 成功返回
return response._data
},
// 错误处理
onResponseError({ response }) {
handleError<T>(response)
return Promise.reject(response?._data ?? null)
},
// 合并参数
...option,
})
}
// 自动导出
export const useHttp = {
get: <T>(url: string, params?: any, option?: HttpOption<T>) => {
return fetch<T>(url, { method: 'get', params, ...option })
},
post: <T>(url: string, body?: any, option?: HttpOption<T>) => {
return fetch<T>(url, { method: 'post', body, ...option })
},
put: <T>(url: string, body?: any, option?: HttpOption<T>) => {
return fetch<T>(url, { method: 'put', body, ...option })
},
delete: <T>(url: string, body?: any, option?: HttpOption<T>) => {
return fetch<T>(url, { method: 'delete', body, ...option })
},
}
四、配置开发代理
通过server配置代理
server/middleware/proxy.ts
const { public: { apiBase } } = useRuntimeConfig()
export default defineEventHandler(async (event) => {
if (event.node.req.url?.includes('/api')) {
const { url, method, headers } = event.node.req;
const options: any = {}
options.method = method;
options.headers = headers;
if (method != "get" && method != "GET") {
options.body = JSON.stringify(await readBody(event))
}
const resBody = await $fetch(apiBase + url, options);
return resBody
}
});
nuxt.config.ts
...
runtimeConfig: {
public: {
apiBase: "http://192.168.0.94:5569/",
},
},
...