针对请求模块化封装搭配自动化导入(简单易用)
- 目标目录
- 目标代码
- 前提
- 步入正题
- src / utils / index.js
- src /api / index.js
- src /api / request.js
- src /api / service.js
- src /api / utils.js
- src /api / modules / demo.js
- 自动化配置
- vite.config.js
- eslint 校验问题
作者GitHub:https://github.com/gitboyzcf 有兴趣可关注!!!
目标目录
目标代码
<script setup>// 在js中直接调用useRequest() 函数就可以获取到配置的接口const { API_DEMO_POST, API_DEMO_GET } = useRequest()// 使用非常简单API_DEMO_GET({page: 1, pageSize: 10}).then(res => { // 请求返回结果})
</script>
接下来看下面配置👇
前提
这里用到的相关npm包
- element-plus 在这里用到了消息提示
- axios 网络请求库
- vueuse Vue hooks库
- nprogress 加载进度条
- consola 好看的日志打印
以上包根据自己需求修改即可、可有可无
步入正题
src / utils / index.js
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) returnconst 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
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
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
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()breakcase '400':// 不是正确的 codereturn requestError(response)case '401':// 错误登录return throttleToLogin()default:// 不是正确的 codereturn requestError(response)}}}, (error) => {NProgress.done()console.log(error)const status = error.response?.statusswitch (status) {// TODO 再考虑下怎么判断是跨域问题case undefined:case null:httpLogError(error, '网路错误或请求跨域')breakcase 400:httpLogError(error, '请求错误')breakcase 401:httpLogError(error, '未授权,请登录')breakcase 403:httpLogError(error, '拒绝访问')breakcase 404:httpLogError(error, `请求地址出错: ${error.response.config.url}`)breakcase 408:httpLogError(error, '请求超时')breakcase 500:httpLogError(error, '服务器内部错误')breakcase 501:httpLogError(error, '服务未实现')breakcase 502:httpLogError(error, '网关错误')breakcase 503:httpLogError(error, '服务不可用')breakcase 504:httpLogError(error, '网关超时')breakcase 505:httpLogError(error, 'HTTP版本不受支持')breakdefault:httpLogError(error, '请求错误')break}msg('error', error.message)return Promise.reject(error)})return request
}export const service = createService()
src /api / utils.js
import { msg as nMsg } from '@/utils'
import consola from 'consola'export const httpLogError = (error, msg) => {error.message = msgconsola.error(new Error(msg))
}export const requestError = (response) => {return new Promise((_, reject) => {const { data } = responseconst msg = `api请求出错 ${response.config.url}:${data.message}`nMsg('error', msg)consola.error(new Error(msg))reject(data)})
}
src /api / modules / demo.js
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
npm install unplugin-auto-import -D
or
pnpm install unplugin-auto-import -D
or
yarn add unplugin-auto-import -D
vite.config.js
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 报红 说未定义
- 上面
vite.config.js
中注释部分放开,运行项目根据这个./.eslintrc-auto-import.json
相对路径会生成该 js 文件 。 注:生成后 把enabled
属性改为 false 以免再次生成 - .在根目录的
eslintrc.cjs
eslint配置文件中添加下面代码👇module.exports = {// ...'extends': [// ...'./.eslintrc-auto-import.json'] }
到这里就结束了,后续还会更新 前端 系列相关,还请持续关注!
感谢阅读,若有错误可以在下方评论区留言哦!!!
推荐文章👇
Vue3-Composition API 快速上手(简单易懂)