vite 环境变量配置 及 axios 二次封装

836 阅读3分钟

配置环境变量

  • image.png
  • 先创建这第三个文件 分别是 开发环境 生产环境 测试环境的配置 到时候就能取到里面的值

    • .env.development

      • VUE_APP_BASE_URL = http://localhost:3000/
        VUE_APP_BASE_NAME = name
        
    • .env.production

      • VUE_APP_BASE_URL = http://localhost:3000/
        VUE_APP_BASE_NAME = name
        
    • .env.test

      • VUE_APP_BASE_URL = http://localhost:3000/
        VUE_APP_BASE_NAME = name
        
      • 如果使用的是 vite 那么 开头要改成 VITE_BASE_RUL 才能获取到其中的配置 可以自行打印一下
  • 可以通过 console.log(import.meta.url) 直接取

  • 我这里重新配置了

    • config.ts
    • let BASE_URL = ''
      const TIME_OUT = 10000
      ​
      if (import.meta.env.MODE === 'development') {
        BASE_URL = 'http://123.207.32.32:8000/'
      } else if (import.meta.env.MODE === 'production') {
        BASE_URL = ''
      } else {
        BASE_URL = ''
      }
      ​
      export { BASE_URL, TIME_OUT }
      
    • 跟下面的 axios 一起封装使用

axios 安装

  • yarn add axios -S
    

封装

  • 使用了 ts 进行类型约束

  • 目录结构 request 文件夹下的的 axios 的二次封装 跟上面的环境变量一块的

  • image.png
  • request type.ts

    • import type { AxiosRequestConfig, AxiosResponse } from 'axios'
      // 定义传入的实例的类
      export interface HYRequestInterceptors<T = AxiosResponse> {
        requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
        requestInterceptorCatch?: (error: any) => any
        responseInterceptor?: (res: T) => T
        responseInterceptorCatch?: (error: any) => any
      }
      ​
      export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
        interceptors?: HYRequestInterceptors<T>
        showLoading?: boolean
      }
      
  • request index.ts

    • 使用类进行封装 添加了 请求拦截 和响应拦截
    • 并且拦截可以是全布实例的 或者每个实例传入 config 单独配置的
    • 其中引入了 element 的过渡加载 不需要的可以自行删除相关代码
    • import axios from 'axios'
      import type { AxiosInstance } from 'axios'
      import type { HYRequestInterceptors, HYRequestConfig } from './type'
      // 引入加载过渡
      import { ElLoading } from 'element-plus'
      // 加载动画显示隐藏
      const DEAFULT_LOADING = trueclass HYRequest {
        // 属性
        instance: AxiosInstance
        interceptors?: HYRequestInterceptors
        showLoading: boolean
        loading?: any
        // 构造函数 传入配置
        constructor(config: HYRequestConfig) {
          // 创建axios实例
          this.instance = axios.create(config)
      ​
          // 保存基本信息
          this.showLoading = config.showLoading ?? DEAFULT_LOADING
          this.interceptors = config.interceptors
      ​
          // 使用拦截器
          // 1.从config中取出的拦截器是对应的实例的拦截器
          this.instance.interceptors.request.use(
            this.interceptors?.requestInterceptor,
            this.interceptors?.requestInterceptorCatch
          )
          this.instance.interceptors.response.use(
            this.interceptors?.responseInterceptor,
            this.interceptors?.responseInterceptorCatch
          )
      ​
          // 2.添加所有的实例都有的拦截器
          this.instance.interceptors.request.use(
            (config) => {
              // 动画的显示和隐藏 
              if (this.showLoading) {
                this.loading = ElLoading.service({
                  lock: true,
                  text: '正在请求数据....',
                  background: 'rgba(0, 0, 0, 0.5)',
                })
              }
              return config
            },
            (err) => {
              return err
            }
          )
          // 响应拦截器
          this.instance.interceptors.response.use(
            (res) => {
              // 将loading移除
              this.loading?.close()
      ​
              const data = res.data
              if (data.returnCode === '-1001') {
                console.log('请求失败~, 错误信息')
              } else {
                return data
              }
            },
            (err) => {
              // 将loading移除
              this.loading?.close()
      ​
              // 例子: 判断不同的HttpErrorCode显示不同的错误信息
              if (err.response.status === 404) {
                console.log('404的错误~')
              }
              return err
            }
          )
        }
        // 方法
        request<T>(config: HYRequestConfig<T>): Promise<T> {
          return new Promise((resolve, reject) => {
            // 1.单个请求对请求config的处理
            if (config.interceptors?.requestInterceptor) {
              config = config.interceptors.requestInterceptor(config)
            }
      ​
            // 2.判断是否需要显示loading
            if (config.showLoading === false) {
              this.showLoading = config.showLoading
            }
      ​
            this.instance
              .request<any, T>(config)
              .then((res) => {
                // 1.单个请求对数据的处理
                if (config.interceptors?.responseInterceptor) {
                  res = config.interceptors.responseInterceptor(res)
                }
                // 2.将showLoading设置true, 这样不会影响下一个请求
                this.showLoading = DEAFULT_LOADING
      ​
                // 3.将结果resolve返回出去
                resolve(res)
              })
              .catch((err) => {
                // 将showLoading设置true, 这样不会影响下一个请求
                this.showLoading = DEAFULT_LOADING
                reject(err)
                return err
              })
          })
        }
        // 封装四个请求
        get<T>(config: HYRequestConfig<T>): Promise<T> {
          return this.request<T>({ ...config, method: 'GET' })
        }
      ​
        post<T>(config: HYRequestConfig<T>): Promise<T> {
          return this.request<T>({ ...config, method: 'POST' })
        }
      ​
        delete<T>(config: HYRequestConfig<T>): Promise<T> {
          return this.request<T>({ ...config, method: 'DELETE' })
        }
      ​
        patch<T>(config: HYRequestConfig<T>): Promise<T> {
          return this.request<T>({ ...config, method: 'PATCH' })
        }
      }
      // 默认暴露出定义的类 其他地方引入 并且使用就行了
      export default HYRequest
      ​
      
  • service index.ts

    •  // service统一出口
       import HYRequest from './request'
       // 全局环境变量
       import { BASE_URL, TIME_OUT } from './request/config'import localCache from '@/utils/cache'
       // 封装一个 实例
       const hyRequest = new HYRequest({
         // 属性 也就是基本配置
         baseURL: BASE_URL,
         timeout: TIME_OUT,
         // 拦截器
         interceptors: {
           requestInterceptor: (config: any) => {
             // 携带token的拦截
             const token = localCache.getCache('token')
             if (token) {
               config.headers.Authorization = `Bearer ${token}`
             }
             return config
           },
           requestInterceptorCatch: (err) => {
             return err
           },
           responseInterceptor: (res) => {
             return res
           },
           responseInterceptorCatch: (err) => {
             return err
           },
         },
       })
       ​
       export default hyRequest
       ​
      

使用

  • 以封装 login 作为例子

  • type.ts

    • // 输入数据的约束
      export interface IAccount {
        name: string
        password: string
      }
      // 对登录返回数据的 约束
      export interface ILoginResult {
        id: number
        name: string
        token: string
      }
      ​
      export interface IDataType<T = any> {
        code: number
        data: T
      }
      ​
      
  • login.ts

    • // 引入封装的实例对象
      import hyRequest from '../index'
      // 引入定义的 类
      import { IAccount, IDataType, ILoginResult } from './type'
      ​
      enum LoginAPI {
        AccountLogin = '/login',
        LoginUserInfo = '/users/', // 用法: /users/1
      }
      // 登录方法 传入账号密码 发送 post 请求
      export function accountLoginRequest(account: IAccount) {
        return hyRequest.post<IDataType<ILoginResult>>({
          url: LoginAPI.AccountLogin,
          data: account,
        })
      }
      ​
      export function requestUserInfoById(id: number) {
        return hyRequest.get<IDataType>({
          url: LoginAPI.LoginUserInfo + id,
          showLoading: false,
        })
      }
      
  • 然后把这几个函数导出到登录模块中使用就行了 也可以在 vuex 中使用

  • 再举一个实例

    • main.ts 下测试

    • import { createApp } from 'vue'
      import App from './App.vue'import ElementPlus from 'element-plus'import router from './router'
      import store from './store'
      // 引入封装的 axios
      import hyRequest from './service'const app = createApp(App)
      app.use(ElementPlus)
      app.use(router)
      app.use(store)
      app.mount('#app')
      // 环境变量
      console.log(import.meta.env)
      // 
      hyRequest
        .request({
          url: '/home/multidata',
          method: 'GET',
          headers: {},
          interceptors: {
            requestInterceptor: (config: any) => {
              console.log('单独请求的config')
              config.headers['token'] = '123'
              return config
            },
            responseInterceptor: (res) => {
              console.log('单独响应的response')
              return res
            },
          },
        })
        .then((res) => {
          console.log(res)
        })
      ​
      
    • image.png