Nuxt3通用请求
新建utils目录
1.文件request.ts
// 文件目录:service/index.ts
import { UseFetchOptions } from "nuxt/app";
import { useNuxtApp } from "#app";
// HTTP 请求的方法类型
type Methods = "GET" | "POST" | "DELETE" | "PUT";
// URL 基地址
const BASE_URL = "/api/";
// 请求结果数据格式
export interface IResultData<T> {
code: number;
data: T;
msg: string;
}
/**
* api请求封装,使用useFetch函数或$fetch函数
* @param { string } url 请求地址
* @param { string } method 请求方法
* @param { object } data 请求数据
* @param { UseFetchOptions } options 请求选项
*/
class HttpRequest {
request<T = any>(url: string, method: Methods, data: any, options?: UseFetchOptions<T>) {
return new Promise((resolve, reject) => {
// 继承UseFetchOptions类型,包含了baseURL和method两个属性
const newOptions: UseFetchOptions<T> = {
baseURL: BASE_URL,
method,
...options,
};
const token = useCookie('token');
if (token.value) {
newOptions.headers = {
Authorization: `Bearer ${token.value}`
};
}
// 根据请求方法处理请求的数据
if (method === "GET" || method === "DELETE") {
// 将数据设置为newOptions的params属性
newOptions.params = data;
}
if (method === "POST" || method === "PUT") {
// 将数据设置为newOptions的body属性
newOptions.body = data;
}
const nuxtApp = useNuxtApp();
// 选择合适的请求方法
const fetchMethod = (process.client && !nuxtApp.isHydrating) ? nuxtApp.$request : useFetch as any;
// 发送请求
fetchMethod(url, newOptions)
.then((res: any) => {
resolve(res.status? res.data.value:res);
})
.catch((error: any) => {
let errorMessage = "服务端错误";
if (error.response && error.response._data) {
let data = error.response._data;
if (typeof error.response._data === 'string') {
try {
data = JSON.parse(error.response._data);
} catch (e) {
errorMessage = error.response._data;
}
}
if (data.errors) {
const errorMessages = [];
for (const key in data.errors) {
errorMessages.push(`${data.errors[key].join(', ')}`);
}
errorMessage = errorMessages.join('; ') || errorMessage;
} else {
errorMessage = data.message || errorMessage;
}
}
if (process.client) {
Message.error(errorMessage);
}
if (error.response &&
(error.response._data.code === 40001 || error.response._data.code === 40002 || error.response._data.code === 40003)) {
resolve(error.response._data);
}
reject(error.response?error.response._data:errorMessage);
});
});
}
// 封装常用方法
get<T = any>(url: string, params?: any, options?: UseFetchOptions<T>) {
return this.request(url, "GET", params, options);
}
post<T = any>(url: string, data?: any, options?: UseFetchOptions<T>) {
return this.request(url, "POST", data, options);
}
put<T = any>(url: string, data: any, options?: UseFetchOptions<T>) {
return this.request(url, "PUT", data, options);
}
delete<T = any>(url: string, params: any, options?: UseFetchOptions<T>) {
return this.request(url, "DELETE", params, options);
}
}
// 实例化 HttpRequest 并导出
const httpRequest = new HttpRequest();
export default httpRequest;
2.文件api.ts
import httpRequest from "~/utils/request";
export const index_portal = () => {
return httpRequest.post('/v1/index/get_index_portal')
}
export const register_email_code = (params: any) => {
return httpRequest.post('/v1/auth/verify-codes/email', params)
}
新建plugins目录
1.文件同样request.ts 这里是$fetch水合请求的
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const $request = $fetch.create({
baseURL: config.public.apiUrl,
/** 请求拦截器 */
onRequest: ({ options }) => {
const userAuth = useCookie("token");
if (userAuth.value) {
options.headers = options.headers ?? {};
(options.headers as Record<string, string>).Authorization = `Bearer ${userAuth.value}`;
}
},
/** 请求错误拦截器,比如服务器无法连接会触发 */
onRequestError({ request, error }) {},
/** 响应拦截器 */
onResponse({ response }) {
// 成功的状态才进行解包
if (response.status >= 200 && response.status < 300) {
response._data = response._data ?? null;
}
},
/** 响应错误拦截器 */
onResponseError(_context) {}
});
return {
provide: {
request: $request
}
};
});
请求案例
const getQuestion = async()=>{
const res:any = await get_questions({
page: page.value,
limit: pageSize.value,
})
if (res.code == 20000) {
list.value = res.data.list
total.value = res.data.total
}
}
代理转发配置
根目录创建.env
# 请求接口地址
VITE_REQUEST_BASE_URL = '/v1'
VITE_SERVER_NAME = 'https://xxx.xxx.com/api'
新建目录server/api
新建文件[…].ts
// @ts-ignore
import {joinURL} from "ufo";
// @ts-ignore
import {proxyRequest} from "h3";
export default defineEventHandler(async (event:any) =>{
const proxyUrl = useRuntimeConfig().normal_url
const path = event.path.replace(/^/api//,'')
const target = joinURL(proxyUrl,path)
return proxyRequest(event,target)
})
在nuxt.config.ts加入以下转发代码
runtimeConfig: { // 运行时常量
normal_url:process.env.VITE_SERVER_NAME,
public: { // 客户端-服务的都能访问
// baseUrl: process.env.VITE_SERVER_NAME
},
},
Nuxt3通用Pinia
安装以下模块
pnpm add @pinia-plugin-persistedstate/nuxt
pnpm add @pinia/nuxt
pnpm add pinia-plugin-persist
pnpm add pinia
在nuxt.config.ts引入
modules: [
'@pinia/nuxt',
'@pinia-plugin-persistedstate/nuxt',
],
新建store目录
随便新建个文件counter.ts
import { defineStore } from 'pinia'
interface CounterState {
setting:any
}
// @ts-ignore
export const useCounter = defineStore('counter', {
state: (): CounterState => ({
setting: {}
}),
actions: {
increment() {
this.setting
}
},
getters: {
doubleCount() {
return this.setting
}
},
persist: process.client && {
storage: persistedState.cookiesWithOptions({
sameSite: 'strict',
}),
paths: ['setting']
}
})