Vite4、Vue3、Axios 针对请求模块化封装搭配自动化导入(简单易用)

针对请求模块化封装搭配自动化导入(简单易用)

  • 目标目录
  • 目标代码
  • 前提
  • 步入正题
    • [src / utils / index.js](#src / utils / index.js)
    • [src /api / index.js](#src /api / index.js)
    • [src /api / request.js](#src /api / request.js)
    • [src /api / service.js](#src /api / service.js)
    • [src /api / utils.js](#src /api / utils.js)
    • [src /api / modules / demo.js](#src /api / modules / demo.js)
  • 自动化配置

作者GitHub:https://github.com/gitboyzcf 有兴趣可关注!!!

目标目录

目标代码

javascript 复制代码
<script setup>
    // 在js中直接调用useRequest() 函数就可以获取到配置的接口
	const { API_DEMO_POST, API_DEMO_GET } = useRequest()
	// 使用非常简单
	API_DEMO_GET({page: 1, pageSize: 10}).then(res => {  
		// 请求返回结果
	})
</script>

接下来看下面配置👇

前提

这里用到的相关npm包

以上包根据自己需求修改即可、可有可无

步入正题

src / utils / index.js

javascript 复制代码
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { ElMessage } from 'element-plus'
/**
 * 获取资源路径
 * @param {相对路径} relativePath
 *    如果要动态获取assets的文件文件夹下的images中的图片
 *      relativePath 传入 assets/images/name.png
 * @returns 文件所在路径
 */
const getStaticResource = (relativePath) => {
  return new URL(`../${relativePath}`, import.meta.url)
}

/**
 * 消息提示
 * @param {弹出消息类型=》 info error warning success loading } type
 * @param {弹出消息文本} message
 * @param {弹出时间} duration
 * @param {弹出消息偏移} offset
 */
const msg = (type, message, duration = 2000, offset = 90) => {
  ElMessage({
    message,
    type,
    duration,
    offset
  })
}

/**
 * 模块化方式处理 默认处理 modules文件夹下的所有js文件 内容以export default导出的文件
 * @param { 模块内容集合 } moduleContext
 * @returns modules集合
 */
const modulesHandle = (moduleContext = {}) => {
  if (!Object.keys(moduleContext).length) return
  const modules = {}
  Object.keys(moduleContext).forEach((v) => {
    for (let key in moduleContext[v].default) {
      modules[key] = moduleContext[v].default[key]
    }
  })
  return modules
}

export { getStaticResource, modulesHandle, NProgress, msg }

src /api / index.js

javascript 复制代码
import { modulesHandle } from '@/utils'

const apis = modulesHandle(import.meta.glob('./modules/**/*.js', { eager: true }))
export const useRequest = () => apis

mport.meta.glob函数从文件系统导入多个模块,详情请看官网 https://cn.vitejs.dev/guide/features#glob-import

src /api / request.js

javascript 复制代码
import { service } from './service'
function createRequest(service) {
  function request(config) {
  	// config 自定义配置
    // axios默认配置
    const configDefault = {
      baseURL: import.meta.env.VITE_APP_API_BASEURL, // 所有通过此配置的基础地址 在.env文件配置
      timeout: 15000, // 请求超时时间
      responseType: 'json', // 响应类型
      headers: {
        // 请求头配置...
      }
    }
    const requestConfig = Object.assign(configDefault, config)
    return service(requestConfig)
  }
  return request
}

export const request = createRequest(service)

src /api / service.js

javascript 复制代码
import axios from 'axios'
import { httpLogError, requestError, throttleToLogin } from './utils'
import { msg, NProgress } from '@/utils'
import consola from 'consola'

export function createService() {
  const request = axios.create()
  request.interceptors.request.use(
    (request) => {
      NProgress.start()
      return request
    },
    (err) => {
      NProgress.done()
      return Promise.reject(err)
    }
  )

  request.interceptors.response.use(
    (response) => {
      NProgress.done()
      const dataAxios = response.data
      // 这个状态码是和后端约定的
      const { code, data } = dataAxios

      // 根据 code 进行判断
      if (code === undefined) {
        return dataAxios
      } else {
        // 目前和公司后端口头约定是字符串,以防万一强制转字符串
        switch (`${code}`) {
          // code === 200 | 2 代表没有错误
          case '200':
            consola.withTag(`${response.config.url}`).success()
            return data
          // code === 400001004 代表token 过期打回登录页
          case '400001004':
            throttleToLogin()
            break
          case '400':
            // 不是正确的 code
            return requestError(response)
          case '401':
            // 错误登录
            return throttleToLogin()
          default:
            // 不是正确的 code
            return requestError(response)
        }
      }
    }, 
    (error) => {
      NProgress.done()
      console.log(error)
      const status = error.response?.status
      switch (status) {
        // TODO 再考虑下怎么判断是跨域问题
        case undefined:
        case null:
          httpLogError(error, '网路错误或请求跨域')
          break
        case 400:
          httpLogError(error, '请求错误')
          break
        case 401:
          httpLogError(error, '未授权,请登录')
          break
        case 403:
          httpLogError(error, '拒绝访问')
          break
        case 404:
          httpLogError(error, `请求地址出错: ${error.response.config.url}`)
          break
        case 408:
          httpLogError(error, '请求超时')
          break
        case 500:
          httpLogError(error, '服务器内部错误')
          break
        case 501:
          httpLogError(error, '服务未实现')
          break
        case 502:
          httpLogError(error, '网关错误')
          break
        case 503:
          httpLogError(error, '服务不可用')
          break
        case 504:
          httpLogError(error, '网关超时')
          break
        case 505:
          httpLogError(error, 'HTTP版本不受支持')
          break
        default:
          httpLogError(error, '请求错误')
          break
      }
      msg('error', error.message)
      return Promise.reject(error)
    }
  )
  return request
}

export const service = createService()

src /api / utils.js

javascript 复制代码
import { msg as nMsg } from '@/utils'
import consola from 'consola'

export const httpLogError = (error, msg) => {
  error.message = msg
  consola.error(new Error(msg))
}

export const requestError = (response) => {
  return new Promise((_, reject) => {
    const { data } = response
    const msg = `api请求出错 ${response.config.url}:${data.message}`
    nMsg('error', msg)
    consola.error(new Error(msg))
    reject(data)
  })
}

src /api / modules / demo.js

javascript 复制代码
import { request } from '@/api/request.js'
export default {
  API_DEMO_POST(data = {}) {
    return request({
      baseURL: '/mock/login',
      url: 'api/mock',
      method: 'post',
      data
    })
  },

  API_DEMO_GET(params = {}) {
    return request({
      url: '/demo/get',
      method: 'get',
      params
    })
  }
}

自动化配置

安装 unplugin-auto-import/vite插件 https://github.com/unplugin/unplugin-auto-import#readme

bash 复制代码
npm install unplugin-auto-import -D 
or
pnpm install unplugin-auto-import -D
or
yarn add unplugin-auto-import -D

vite.config.js

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: [
        'vue',
        'vue-router',
        'pinia',
        {
          '@/api': ['useRequest']
        }
      ],
      // eslintrc: {
        // enabled: true, // Default `false`
        // filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
        // globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
      }
    })
  ]
})

eslint 校验问题

在vue文件中直接使用时 vscode 报红 说未定义

  1. 上面 vite.config.js中注释部分放开,运行项目根据这个./.eslintrc-auto-import.json相对路径会生成该 js 文件 。 注:生成后 把 enabled属性改为 false 以免再次生成

  2. .在根目录的 eslintrc.cjseslint配置文件中添加下面代码👇

    javascript 复制代码
    module.exports = {
       // ...
      'extends': [
    	// ...
        './.eslintrc-auto-import.json'
      ]
    }

到这里就结束了,后续还会更新 前端 系列相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!

推荐文章👇

Vue3-Composition API 快速上手(简单易懂)

相关推荐
passerby606122 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了29 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅32 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
吹牛不交税2 小时前
admin.net-v2 框架使用笔记-netcore8.0/10.0版
vue.js·.netcore