针对请求模块化封装搭配自动化导入(简单易用)
- 目标目录
- 目标代码
- 前提
- 步入正题
- 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) 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
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()
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
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
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 快速上手(简单易懂)