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 快速上手(简单易懂)

相关推荐
2401_882727578 分钟前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
会发光的猪。42 分钟前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客1 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记1 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
前端李易安1 小时前
Webpack 热更新(HMR)详解:原理与实现
前端·webpack·node.js
红绿鲤鱼1 小时前
React-自定义Hook与逻辑共享
前端·react.js·前端框架
周全全1 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
Domain-zhuo2 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
小丁爱养花2 小时前
前端三剑客(三):JavaScript
开发语言·前端·javascript
ZwaterZ2 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue