站长资讯网
最全最丰富的资讯网站

聊聊vite+vue3.0+ts中如何封装axios?

聊聊vite+vue3.0+ts中如何封装axios?

目前,关于vue中使用axios的作为前端和后端接口交互工具的用法文章,网络某博客上数不胜数。因为项目从0到1开始需要基于vite+vue3.0+ts中封装axios,所以今天让小编来给大家安排axios整合vite+vue3.0+ts的具体封装步骤。记录一下自己封装步骤,跟着我的步伐,撸起来。。。(学习视频分享:vue视频教程)

以下内容均基于下方视频完结后的扩展:

2021最新最详细的Vite+vue3+Volar+Ts+Element-plus框架学习项目视频

1、安装axios

npm i axios

注意:这里的安装命令就是默认安装最新版本的axios

2、封装请求错误代码提示error-code-type.ts

  • 代码如下:
export const errorCodeType = function(code:string):string{     let errMessage:string = "未知错误"     switch (code) {         case 400:          errMessage = '错误的请求'          break          case 401:          errMessage = '未授权,请重新登录'          break         case 403:          errMessage = '拒绝访问'          break          case 404:          errMessage = '请求错误,未找到该资源'          break          case 405:          errMessage = '请求方法未允许'          break          case 408:          errMessage = '请求超时'          break          case 500:          errMessage = '服务器端出错'          break          case 501:          errMessage = '网络未实现'          break          case 502:          errMessage = '网络错误'          break          case 503:          errMessage = '服务不可用'          break          case 504:          errMessage = '网络超时'          break          case 505:          errMessage = 'http版本不支持该请求'          break          default:          errMessage = `其他连接错误 --${code}`     }     return errMessage }

3、封装request.ts

这里用到的element-plus大家可以参考其官网安装即可,传送门:

element-plus官网

安装命令: npm install element-plus --save
  • 代码如下:
import axios from 'axios'; import { errorCodeType } from '@/script/utils/error-code-type'; import { ElMessage, ElLoading } from 'element-plus';  // 创建axios实例 const service = axios.create({     // 服务接口请求     baseURL: import.meta.env.VITE_APP_BASE_API,     // 超时设置     // timeout: 15000,     headers:{'Content-Type':'application/json;charset=utf-8'} })  let loading:any; //正在请求的数量 let requestCount:number = 0 //显示loading const showLoading = () => {     if (requestCount === 0 && !loading) {         //加载中显示样式可以自行修改         loading = ElLoading.service({             text: "拼命加载中,请稍后...",             background: 'rgba(0, 0, 0, 0.7)',             spinner: 'el-icon-loading',         })     }     requestCount++; } //隐藏loading const hideLoading = () => {     requestCount--     if (requestCount == 0) {         loading.close()     } }  // 请求拦截 service.interceptors.request.use(config => {     showLoading()     // 是否需要设置 token放在请求头     // config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改     // get请求映射params参数     if (config.method === 'get' && config.params) {         let url = config.url + '?';         for (const propName of Object.keys(config.params)) {             const value = config.params[propName];             var part = encodeURIComponent(propName) + "=";             if (value !== null && typeof(value) !== "undefined") {                  // 对象处理                 if (typeof value === 'object') {                     for (const key of Object.keys(value)) {                         let params = propName + '[' + key + ']';                         var subPart = encodeURIComponent(params) + "=";                         url += subPart + encodeURIComponent(value[key]) + "&";                     }                 } else {                     url += part + encodeURIComponent(value) + "&";                 }             }         }         url = url.slice(0, -1);         config.params = {};         config.url = url;     }     return config }, error => {     console.log(error)     Promise.reject(error) })  // 响应拦截器 service.interceptors.response.use((res:any) => {         hideLoading()         // 未设置状态码则默认成功状态         const code = res.data['code'] || 200;         // 获取错误信息         const msg = errorCodeType(code) || res.data['msg'] || errorCodeType('default')         if(code === 200){             return Promise.resolve(res.data)         }else{             ElMessage.error(msg)             return Promise.reject(res.data)         }     },     error => {         console.log('err' + error)         hideLoading()         let { message } = error;         if (message == "Network Error") {             message = "后端接口连接异常";         }         else if (message.includes("timeout")) {             message = "系统接口请求超时";         }         else if (message.includes("Request failed with status code")) {             message = "系统接口" + message.substr(message.length - 3) + "异常";         }         ElMessage.error({             message: message,             duration: 5 * 1000         })         return Promise.reject(error)     } )  export default service;

4、自动导入vue3相关函数(auto-imports.d.ts)

  • auto-imports.d.ts放在src目录下
  • 注意:需要安装yarn add unplugin-auto-import或者npm i unplugin-auto-import -D
  • 安装完重启项目
  • 代码如下:
declare global {   const computed: typeof import('vue')['computed']   const createApp: typeof import('vue')['createApp']   const customRef: typeof import('vue')['customRef']   const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']   const defineComponent: typeof import('vue')['defineComponent']   const effectScope: typeof import('vue')['effectScope']   const EffectScope: typeof import('vue')['EffectScope']   const getCurrentInstance: typeof import('vue')['getCurrentInstance']   const getCurrentScope: typeof import('vue')['getCurrentScope']   const h: typeof import('vue')['h']   const inject: typeof import('vue')['inject']   const isReadonly: typeof import('vue')['isReadonly']   const isRef: typeof import('vue')['isRef']   const markRaw: typeof import('vue')['markRaw']   const nextTick: typeof import('vue')['nextTick']   const onActivated: typeof import('vue')['onActivated']   const onBeforeMount: typeof import('vue')['onBeforeMount']   const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']   const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']   const onDeactivated: typeof import('vue')['onDeactivated']   const onErrorCaptured: typeof import('vue')['onErrorCaptured']   const onMounted: typeof import('vue')['onMounted']   const onRenderTracked: typeof import('vue')['onRenderTracked']   const onRenderTriggered: typeof import('vue')['onRenderTriggered']   const onScopeDispose: typeof import('vue')['onScopeDispose']   const onServerPrefetch: typeof import('vue')['onServerPrefetch']   const onUnmounted: typeof import('vue')['onUnmounted']   const onUpdated: typeof import('vue')['onUpdated']   const provide: typeof import('vue')['provide']   const reactive: typeof import('vue')['reactive']   const readonly: typeof import('vue')['readonly']   const ref: typeof import('vue')['ref']   const resolveComponent: typeof import('vue')['resolveComponent']   const shallowReactive: typeof import('vue')['shallowReactive']   const shallowReadonly: typeof import('vue')['shallowReadonly']   const shallowRef: typeof import('vue')['shallowRef']   const toRaw: typeof import('vue')['toRaw']   const toRef: typeof import('vue')['toRef']   const toRefs: typeof import('vue')['toRefs']   const triggerRef: typeof import('vue')['triggerRef']   const unref: typeof import('vue')['unref']   const useAttrs: typeof import('vue')['useAttrs']   const useCssModule: typeof import('vue')['useCssModule']   const useCssVars: typeof import('vue')['useCssVars']   const useSlots: typeof import('vue')['useSlots']   const watch: typeof import('vue')['watch']   const watchEffect: typeof import('vue')['watchEffect'] } export {}

5、自动导入Element Plus 相关函数(components.d.ts)

  • 注意:需要安装npm i unplugin-vue-components -D或者yarn add unplugin-vue-components
  • 安装完重启项目
import '@vue/runtime-core'  declare module '@vue/runtime-core' {   export interface GlobalComponents {     ElCard: typeof import('element-plus/es')['ElCard']     ElCol: typeof import('element-plus/es')['ElCol']     ElContainer: typeof import('element-plus/es')['ElContainer']     ElFooter: typeof import('element-plus/es')['ElFooter']     ElHeader: typeof import('element-plus/es')['ElHeader']     ElMain: typeof import('element-plus/es')['ElMain']     ElOption: typeof import('element-plus/es')['ElOption']     ElPagination: typeof import('element-plus/es')['ElPagination']     ElRadioButton: typeof import('element-plus/es')['ElRadioButton']     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']     ElRow: typeof import('element-plus/es')['ElRow']     ElSelect: typeof import('element-plus/es')['ElSelect']     ElTable: typeof import('element-plus/es')['ElTable']     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']     Loading: typeof import('element-plus/es')['ElLoadingDirective']   } }  export {}

6、vite.config.ts文件配置

  • 注意:需要安装npm i unplugin-icons或者yarn add unplugin-icons
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import Icons from "unplugin-icons/vite"; import IconsResolver from "unplugin-icons/resolver"; import AutoImport from "unplugin-auto-import/vite"; import Components from "unplugin-vue-components/vite"; import { ElementPlusResolver } from "unplugin-vue-components/resolvers"; import { loadEnv } from 'vite'; import path from 'path'; // 路径 const pathSrc = path.resolve(__dirname,'src')  // https://vitejs.dev/config/ export default({ command, mode }) => {     return defineConfig({         plugins: [             vue(),             AutoImport({                 // Auto import functions from Vue, e.g. ref, reactive, toRef...                 // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等                 imports: ["vue"],                  // Auto import functions from Element Plus, e.g. ElMessage, ElMessageBox... (with style)                 // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)                 resolvers: [                     ElementPlusResolver(),                      // Auto import icon components                     // 自动导入图标组件                     IconsResolver({                         prefix: "Icon",                     }),                 ],                  dts: path.resolve(pathSrc, "auto-imports.d.ts"),             }),                          // 自动导入 Element Plus 组件             Components({                 resolvers: [                     // Auto register icon components                     // 自动注册图标组件                     IconsResolver({                         enabledCollections: ["ep"],                     }),                     // Auto register Element Plus components                                         ElementPlusResolver(),                 ],                  dts: path.resolve(pathSrc, "components.d.ts"),             }),             // 图标             Icons({                 autoInstall: true,             }),         ],         server:{             host: '127.0.0.1',             //port: Number(loadEnv(mode, process.cwd()).VITE_APP_PORT),             port: 3000,             strictPort: true, // 端口被占用直接退出             https: false,             open: true,// 在开发服务器启动时自动在浏览器中打开应用程序             proxy: {                 // 字符串简写写法                 '^/api': {                     target: mode==='development'?loadEnv(mode, process.cwd()).VITE_APP_DEV_URL:loadEnv(mode, process.cwd()).VITE_APP_PROD_URL,                     changeOrigin: true,                     rewrite: (path) => path.replace(/^/api/, '')                 }             },             hmr:{                 overlay: false // 屏蔽服务器报错             }         },         resolve:{             alias:{                 '@': pathSrc,             }         },         css:{             // css预处理器             /*preprocessorOptions: {                 scss: {                     additionalData: '@import "@/assets/styles/global.scss";'                 }             }*/              preprocessorOptions: {                less: {                  charset: false,                  additionalData: '@import "./src/assets/style/global.less";',                 },             },         },         build:{             chunkSizeWarningLimit: 1500, // 分块打包,分解块,将大块分解成更小的块             rollupOptions: {                 output:{                     manualChunks(id) {                         if (id.includes('node_modules')) {                             return id.toString().split('node_modules/')[1].split('/')[0].toString();                         }                     }                 }             }         }     }) }

7、使用axios封装

完整的环境变量配置文件.env.production和.env.development

7.1、项目根目录的development文件内容如下

# 开发环境 VITE_APP_TITLE = "阿绵"  # 端口号  VITE_APP_PORT = "3000"  # 请求接口  VITE_APP_DEV_URL = "http://localhost:8088"  # 前缀  VITE_APP_BASE_API = "/api"

7.2、项目根目录下的production文件内容如下

# 开发环境  VITE_APP_TITLE = "阿绵"  # 端口号  VITE_APP_PORT = "3000"  # 请求接口  VITE_APP_DEV_URL = "http://localhost:8088"  # 前缀  VITE_APP_BASE_API = "/api"

8、在任何vue文件内使用接口:

  • 注意:这里还有一个PageParams全局分页对象:

  • page-params.ts

  • 代码如下:

// 全局统一分页参数类型声明  declare interface PageParams {     pageNum: number, pageSize: number, type?: Model, // 可选参数      readonly sort?: string // 只读可选参数  } interface Model { type?: string } export default PageParams;

总结

本篇讨论的主要内容是:

  1. axios整合vite+vue3.0+ts的具体封装步骤,对于细节方面还没很细,可以扩展更深入封装它

(学习视频分享:web前端开发、编程基础视频)

赞(0)
分享到: 更多 (0)
网站地图   沪ICP备18035694号-2    沪公网安备31011702889846号