功能
axios
用于与后端交互的组件
安装
1pnpm i -S axios
封装业务公共请求
apis/client/types.ts
1import type { AxiosResponse, InternalAxiosRequestConfig } from "axios";
2
3// 业务接口结构
4interface ApiResult<T = any> extends AxiosResponse {
5 code: number;
6 data: T;
7 msg: string;
8 error?: boolean;
9 response?: AxiosResponse;
10}
11
12interface ApiRequestConfig extends InternalAxiosRequestConfig {
13 // 用户自定义配置
14 silent?: boolean;
15}
16
17export type { ApiResult, ApiRequestConfig };
封装公共请求拦截
apis/client/service.ts
1import axios from "axios"; // 引入axios
2import type { AxiosInstance, AxiosResponse, AxiosError } from "axios";
3import type { ApiResult, ApiRequestConfig } from "./types";
4import { ElMessage, ElMessageBox } from "element-plus";
5import router from "@/router/index";
6
7class Service {
8 service: AxiosInstance;
9
10 constructor(baseURL = "/", timeout = 30000) {
11 this.service = axios.create({
12 baseURL,
13 timeout,
14 headers: {
15 "Content-type": "application/json",
16 },
17 });
18 this.interceptors();
19 }
20 interceptors() {
21 // http request 拦截器
22 this.service.interceptors.request.use(
23 (config: ApiRequestConfig) => {
24 return config;
25 },
26 (error: AxiosError) => {
27 ElMessage({
28 showClose: true,
29 message: error.message,
30 type: "error",
31 });
32 return error;
33 }
34 );
35 // http response 拦截器
36 this.service.interceptors.response.use(
37 (response: AxiosResponse) => {
38 const resData = response.data as ApiResult;
39 if (resData.code === 0) {
40 return { data: resData.data, response } as any;
41 } else {
42 const { silent } = response.config as ApiRequestConfig;
43 !silent &&
44 ElMessage({
45 showClose: true,
46 message: response.data.msg || decodeURI(response.headers.msg),
47 type: "error",
48 });
49 if (response.data.data && response.data.data.reload) {
50 localStorage.clear();
51 router.push({ name: "login", replace: true });
52 }
53 return { error: true, response };
54 }
55 },
56 (error: AxiosError) => {
57 if (!error.response) {
58 ElMessageBox.confirm(
59 `
60 <p>检测到请求错误</p>
61 <p>${error}</p>
62 `,
63 "请求报错",
64 {
65 dangerouslyUseHTMLString: true,
66 distinguishCancelAndClose: true,
67 confirmButtonText: "稍后重试",
68 cancelButtonText: "取消",
69 }
70 ).then((r) => r.action.replace.name);
71 return { error: true };
72 }
73
74 switch (error.response.status) {
75 case 500:
76 ElMessageBox.confirm(
77 `
78 <p>检测到接口错误${error}</p>
79 <p>错误码<span style="color:red"> 500 </span>:此类错误内容常见于后台panic,请先查看后台日志,如果影响您正常使用可强制登出清理缓存</p>
80 `,
81 "接口报错",
82 {
83 dangerouslyUseHTMLString: true,
84 distinguishCancelAndClose: true,
85 confirmButtonText: "清理缓存",
86 cancelButtonText: "取消",
87 }
88 ).then(() => {
89 router.push({ name: "login", replace: true });
90 });
91 break;
92 case 404:
93 ElMessageBox.confirm(
94 `
95 <p>检测到接口错误${error}</p>
96 <p>错误码<span style="color:red"> 404 </span>:此类错误多为接口未注册(或未重启)或者请求路径(方法)与api路径(方法)不符--如果为自动化代码请检查是否存在空格</p>
97 `,
98 "接口报错",
99 {
100 dangerouslyUseHTMLString: true,
101 distinguishCancelAndClose: true,
102 confirmButtonText: "我知道了",
103 cancelButtonText: "取消",
104 }
105 ).then(() => {
106 router.push({ name: "login", replace: true });
107 });
108 break;
109 }
110
111 return {
112 error: true,
113 response: error.response,
114 };
115 }
116 );
117 }
118 get<T = any>(
119 url: string,
120 data?: T,
121 options?: Partial<ApiRequestConfig>
122 ): Promise<ApiResult<T>> {
123 return this.service.get(url, { params: data, ...options });
124 }
125 put<T = any, D = any>(
126 url: string,
127 data?: D,
128 options?: Partial<ApiRequestConfig>
129 ): Promise<ApiResult<T>> {
130 return this.service.put(url, data, options);
131 }
132 post<T = any, D = any>(
133 url: string,
134 data?: D,
135 options?: Partial<ApiRequestConfig>
136 ): Promise<ApiResult<T>> {
137 return this.service.post(url, data, options);
138 }
139 delete<T = any>(
140 url: string,
141 options?: Partial<ApiRequestConfig>
142 ): Promise<ApiResult<T>> {
143 return this.service.delete(url, options);
144 }
145}
146
147export default new Service();
MOCK
用于模拟后端的组件
安装
1pnpm i mockjs vite-plugin-mock --save-dev
vite.config.js
1 plugins: [
2 ...
3 viteMockServe({
4 // supportTs:false,
5 // logger:false,
6 mockPath: './src/mock/apis', //解析路径
7 enable: true,
8 watchFiles: true
9 })
10 ],
编写一个 mock 接口
/src/mock/user.ts
1import type { MockMethod } from 'vite-plugin-mock'
2
3export default [
4 {
5 url: '/api/login', // 注意,这里只能是string格式
6 method: 'post',
7 response: (req) => {
8 if (req.body.username == 'admin') {
9 return {
10 code: 0,
11 data: {
12 token: 'safdasdfas'
13 }
14 }
15 } else {
16 return {
17 code: 401,
18 msg: '用户名密码错误'
19 }
20 }
21 }
22 }
23] as MockMethod[] // 这里其实就是定义数据格式的,不了解的同学可以参考typescript的官方文档
scss
scss 是 css 的一种预处理语言
安装
1pnpm i sass sass-loader --save-dev
vite.config.js
1 css: {
2 // css预处理器
3 preprocessorOptions: {
4 scss: {
5 // 引入 mixin.scss 这样就可以在全局中使用 mixin.scss中预定义的变量了
6 // 给导入的路径最后加上 ;
7 //additionalData: '@import "@/assets/main.scss";' //如果在main.ts中引入了,这里无需再次引用
8 }
9 }
10 },
使用
页面标签中加lang="scss"
即可,如果没安装sass
加该标签会语法报错
1<style lang="scss" scoped>
2...
3</style>
发布日期:2000-03-05 01:52 字数:720 用时
tags:Vue