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

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

  • 目标目录
  • 目标代码
  • 前提
  • 步入正题
    • 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 校验问题

1

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

目标目录

1

目标代码

<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 报红 说未定义
err

  1. 上面 vite.config.js中注释部分放开,运行项目根据这个./.eslintrc-auto-import.json相对路径会生成该 js 文件 。 注:生成后 把 enabled属性改为 false 以免再次生成
  2. .在根目录的 eslintrc.cjseslint配置文件中添加下面代码👇
    module.exports = {
       // ...
      'extends': [
    	// ...
        './.eslintrc-auto-import.json'
      ]
    }
    






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

111



推荐文章👇

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/223884.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023中医药国际传承传播大会暨中医药图片和非遗艺术展隆重揭幕

由世界针灸学会联合会、中新社国际传播集团、中国新闻图片网、中国民族医药学会、中国针灸学会联合主办的“2023中医药国际传承传播大会”3日在广东省深圳市举办&#xff0c;“中医药国际传承传播图片展”与“非遗艺术展”在大会举办期间开展迎客。会议聚焦非遗健康、非遗传承等…

案例049:基于微信小程序的校园外卖平台设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【vue】点击导航菜单切换局部页面,打开展示默认栏目,页面刷新等问题

非专业前端&#xff0c;局限性较高&#xff0c;有些问题看起来很小&#xff0c;但是初次接触很棘手&#xff0c;需要查找很多博客&#xff0c;内容也很杂。以下只是过程中总结下来的&#xff0c;要解决的就是标题中的三个问题。 这是我需要达成的效果。 1.第一个是进入导航菜单…

LeetCode:2646. 最小化旅行的价格总和(dfs + 树形dp C++、Java)

目录 2646. 最小化旅行的价格总和 题目描述&#xff1a; 实现代码与解析&#xff1a; DFS DP 原理思路&#xff1a; 2646. 最小化旅行的价格总和 题目描述&#xff1a; 现有一棵无向、无根的树&#xff0c;树中有 n 个节点&#xff0c;按从 0 到 n - 1 编号。给你一个整数…

团队git操作流程

项目的开发要求&#xff1a;&#xff08;1&#xff09;项目组厉员代码提交不少于20次 &#xff08;2&#xff09;项目组厉员每天提交不少于20次 &#xff08;3&#xff09;企业项目开发代码的每天的提交一般提交3-5次 &#xff08;4&#xff09;代码仓库的管理 git的基础操作流…

案例042:基于微信小程序的居住证申报系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

OpenCV-python numpy和基本作图

文章目录 一、实验目的二、实验内容三、实验过程Numpy1.NumPy 操作2.NumPy Ndarray 对象3.NumPy 基本类型4.NumPy 数组属性ndarray.ndimndarray.shapendarray.itemsizendarray.flags 5.NumPy 创建数组numpy.emptynumpy.zerosnumpy.ones 6.NumPy 从已有的数组创建数组numpy.asar…

【Python】Python读Excel文件生成xml文件

目录 ​前言 正文 1.Python基础学习 2.Python读取Excel表格 2.1安装xlrd模块 2.2使用介绍 2.2.1常用单元格中的数据类型 2.2.2 导入模块 2.2.3打开Excel文件读取数据 2.2.4常用函数 2.2.5代码测试 2.2.6 Python操作Excel官方网址 3.Python创建xml文件 3.1 xml语法…

HCL Domino 12系统管理员考试

大家好&#xff0c;才是真的好。 12月份的某一天&#xff0c;趁着风和日丽&#xff0c;天朗气清&#xff0c; 下了舍弃100多美金的狠心&#xff0c;在Pearson Vue官网上报了HCL Domino 12系统管理员考试的名 。时隔十五年后&#xff0c;骑着电动车风风火火地前往某一当地考试中…

AI Pika 生成进击的巨人动漫分镜案例

背景介绍 Pika 是一个使用 AI 生成和编辑视频的平台。它致力于通过 AI 技术使视频制作变得简单和无障碍。 Pika 1.0 是 Pika 的一个重大产品升级&#xff0c;包含了一个新的 AI 模型,可以在各种风格下生成和编辑视频,如 3D 动画&#xff0c;动漫&#xff0c;卡通和电影风格。…

pytorch中的transpose用法

注意&#xff1a;维数从0开始&#xff0c;0维 1维2维…,负数代表从右往左数&#xff0c;-1代表第一维&#xff0c;以此类推 import torch import numpy as np# 创建一个二维数组 arr torch.tensor([[[1, 2],[3, 4]],[[5, 6],[7, 8]]]) print("原始数组&#xff1a;"…

深入理解 Java 虚拟机(JVM)从入门到精通

目录 一、JVM内存结构1、堆&#xff08;Heap&#xff09;&#xff08;1&#xff09;特点&#xff08;2&#xff09;堆内存分配&#xff08;3&#xff09;晋升到老年代的方式&#xff08;4&#xff09;堆内存检验方式2、虚拟机栈&#xff08;VM Stack&#xff09;&#xff08;1&…

Vis.js教程(二):基础关系图实现

首先引用所需要的css和js文件 <link href"https://cdn.bootcdn.net/ajax/libs/vis-network/9.1.6/dist/dist/vis-network.min.css" rel"stylesheet"> <script src"https://cdn.bootcdn.net/ajax/libs/vis-network/9.1.6/standalone/umd/vis-…

python+requests+excel 接口测试

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …

前端编码中快速填充内容--乱数假文

写前端页面的时候&#xff0c;如果要快速插入图片&#xff0c;可以使用 https://picsum.photos/ 详见笔者这篇博文&#xff1a; 工具网站&#xff1a;随机生成图片的网站-CSDN博客 可是&#xff0c;如果要快速填充文字内容该怎么做呢&#xff1f; 以前&#xff0c;我们都是…

【GAMES101】二维变换和齐次坐标

这几天都在抽空学OpenGL、敲leetcode和看games&#xff0c;这里留点笔记给以后复习 games101第一节课在吹水&#xff0c;第二节课讲了线性代数的入门知识&#xff0c;比较简单&#xff0c;这里稍微回顾一下重点&#xff0c;然后开始讲第三节课的二维变换和齐次坐标 目录 向量…

ACM32F42X系列芯片有何性能?为什么可以应用在工业控制 中等产品上

ACM32F42X 芯片的内核基于 ARMv8-M 架构&#xff0c;支持 Cortex-M33 和 Cortex-M4F 指令集。内核支持一 整套 DSP 指令用于数字信号处理&#xff0c;支持单精度 FPU 处理浮点数据&#xff0c;同时还支持 Memory Protection Unit &#xff08;MPU&#xff09;用于提升应用的安全…

C++[面向对象的程序设计]_基础入门(上)(万字总结)(建议收藏!!!)

目录 1. C基础入门 1.1 变量 1.2 常量 1.3 关键字 1.4 标识符命名规则 1.5 数据类型 1.5.1 整型 1.5.2 sizeof 关键字 1.5.3 实型&#xff08;浮点型&#xff09; 1.5.4 字符型 1.5.5 转义字符 1.5.6 字符串类型 1.5.7 布尔类型 1.5.8 数据的输入 1.6 运算符 …

ps快捷键和常见项目总结

处理以像素构成的位图的软件 Mac笔记本快捷键&#xff1a; 打开文件&#xff1a;commandO 图像缩放&#xff1a;command 多个文件切换&#xff1a;同一桌面中&#xff1a;command (英文状态下输入) 切换屏幕模式&#xff1a;F,全屏模式下Tab键可进行切换 首选项—性能&a…

python/matlab图像去雾/去雨综述

图像去雾和去雨是计算机视觉领域的两个重要任务&#xff0c;旨在提高图像质量和可视化效果。本文将综述图像去雾和去雨的算法、理论以及相关项目代码示例。 一、图像去雾算法 基于暗通道先验的方法&#xff1a; 这是广泛应用于图像去雾的经典算法之一。该方法基于一个观察&…