vue3实战教程之axios的封装和环境变量

目录
  • axios
  • 基本使用
  • 配置
  • 封装
  • 请求时添加loading
  • 环境变量
  • 总结

axios

axios: ajax i/o system. 一个可以同时在浏览器和node环境进行网络请求的第三方库

功能特点:

  • 在浏览器中发送 XMLHttpRequests 请求
  • 在 node.js 中发送 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 等等

基本使用

get请求

// 导入的axios是一个实例对象
import axios from 'axios'

// axios方法返回的是promise
const res = await axios.get('https://httpbin.org/get', {
 	// 传递query参数
  params: {
    name: 'Klaus'
  }
})

// 服务器实际返回的数据被放置在data属性中
console.log(res.data)

post请求

const res = await axios.post('https://httpbin.org/post', {
  data: {
    name: 'Klaus'
  }
})

request请求

// axios的所有请求本质上都是在调用axios的request方法
const res = await axios.request({
  url: 'https://httpbin.org/post',
  method: 'post',
  data: {
    name: 'Klaus'
  }
})

all

axios.all本质上就是Promise.all

const res = await axios.all([
  axios.get('https://httpbin.org/get', {
    params: {
      name: 'Klaus'
    }
  }),

  axios.post('https://httpbin.org/post', {
    data: {
      name: 'Klaus'
    }
  })
])

拦截器

// 拦截器必须要在请求和响应之前被注册

// 请求拦截器 --- use方法的两个参数 --- 分别对应resolve和reject
// resolve方法的参数为请求的配置选项
// reject方法的参数为错误对象
axios.interceptors.request.use(
  config => {
    console.log(config)
    return config
  },
  err => console.error(err)
)

// 响应拦截器 --- use方法的两个参数 --- 分别对应resolve和reject
// resolve方法的参数为响应体
// reject方法的参数为错误对象
axios.interceptors.response.use(
  res => {
    return res.data
  },
  err => console.error(err)
)

配置

// 以下都是全局配置
// axios的所有全局配置都可以设置在属性defaults下

// 基本请求公共路径
axios.defaults.baseURL = 'http://httpbin.org'

// 超时时间
axios.defaults.timeout = 10000

// 需要传递的自定义请求头
axios.defaults.headers = {}
// 局部配置
axios
  .get('/get', {
  params: {
    name: 'Klaus',
    age: 18
  },

  // 局部配置可以覆盖全局配置
  timeout: 5000,
  headers: {}
})
  .then((res) => {
  console.log(res.data)
})

封装

如果直接在每一个需要进行网络请求的页面中的引入axios会导致如下问题:

  • 每一个页面都需要引入axios, 就导致axios和逻辑的耦合性过强,如果以后需要进行修改,那么就需要去每一个使用了axios的页面中进行修改

    是十分麻烦且容易出错的

  • 在页面请求的时候,我们会传递许多公共配置,例如BASE_URL,TOKEN等。

所以我们需要对我们的网络请求进行二次封装 --- 一般会放置在src下的service或者api文件夹下

type.ts

import { AxiosRequestConfig, AxiosResponse  } from 'axios'

// 自定义自己的拦截器类型
export interface Interceptor {
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig | Promise<AxiosRequestConfig>,
  requestInterceptorCatch?: (err: any) => any,
  responseInterceptor?: (res: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>,
  responseInterceptorCatch?: (err: any) => any,
}

// 通过接口继承的方式扩展axios的AxiosRequestConfig类型
export interface Config extends AxiosRequestConfig{
  interceptor?: Interceptor
}

env.ts

// 将一些相关配置配置成常量后在引入使用
// 将配置和调用解耦,如果需要修改,直接修改常量的值即可
export const TIME_OUT = 10000
export const BASE_URL = 'https://httpbin.org/'

index.ts

import Api from './api'

import {
  BASE_URL,
  TIME_OUT
} from './env'

const api = new Api({
  baseURL: BASE_URL,
  timeout: TIME_OUT,

  // 不同的实例可能有不同的拦截器
  // 所以我们将拦截器封装成一个扩展属性进行传入
  // interceptor: {
  //   requestInterceptor: config => {
  //     console.log('请求成功')
  //     return config
  //   },
  //   requestInterceptorCatch: err => console.error(err),
  //   responseInterceptor: res => res.data,
  //   responseInterceptorCatch:  err => console.error(err)
  // }
})

export default api

api.ts

import axios from 'axios'
import { ElLoading } from 'element-plus'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { Config } from './type'

// 导出的属性和方法比较多 所以使用类来进行封装
// 因为类具有比较好的封装性
export default class {
  instance: AxiosInstance

  constructor(config: Config) {
    // 每次创建实例的时候,都调用axios.create方法
    // axios.create可以返回一个axios实例
    // 这样保证我们可以使用不同的配置创建多个axios实例
    this.instance = axios.create(config)

    // 如果存在实例级别的拦截器 就使用拦截器
    // 这是针对于每一个请求特有的拦截器 --- 实例拦截
    // 这里的操作也可以通过transformRequest和transformResponse配置项来进行实现
    if (config.interceptor) {
      const { interceptor } = config
      this.instance.interceptors.request.use(interceptor.requestInterceptor, interceptor.requestInterceptorCatch)
      this.instance.interceptors.response.use(interceptor.responseInterceptor, interceptor.responseInterceptorCatch)
    }

    this.registerGlobalInterceptor(config)
  }

  // 这是所有实例共有的拦截器 --- 全局拦截
  // 如果存在多个拦截器,那么多个拦截器都会被执行
  registerGlobalInterceptor(option: Config) {
    this.instance.interceptors.request.use(config => config, err => err)
    this.instance.interceptors.response.use(res => res.data, err => err)
  }

  request(config: AxiosRequestConfig) {
    return this.instance.request(config)
  }
}

请求时添加loading

import axios from 'axios'
import { ElLoading } from 'element-plus'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
import type { Config } from './type'

// el-loading是插件不是组件,element-plus的按需引入并不能正确的引入el-loading的样式
// 所以需要自己手动进行引入el-loading的样式
import 'element-plus/theme-chalk/el-loading.css'

export default class {
  instance: AxiosInstance
  loading: LoadingInstance | undefined

  constructor(config: Config) {
    this.instance = axios.create(config)

    if (config.interceptor) {
      const { interceptor } = config
      this.instance.interceptors.request.use(interceptor.requestInterceptor, interceptor.requestInterceptorCatch)
      this.instance.interceptors.response.use(interceptor.responseInterceptor, interceptor.responseInterceptorCatch)
    }

    this.registerGlobalInterceptor()
  }

  registerGlobalInterceptor() {
    this.instance.interceptors.request.use((config: Config) => {
      // ?? --- 当左侧的操作数为 null 或者 undefined 时,返回右侧操作数,否则返回左侧操作数
      if (config?.showLoading ?? true) {
        // 开启loading
        this.loading =  ElLoading.service({
          lock: true,
          text: 'Loading...',
          background: 'rgba(0, 0, 0, 0.7)',
        })
      }

      return config
    }, err => err)

    this.instance.interceptors.response.use(res => {
      // 关闭loading
      this.loading?.close()

      // axios返回的是字符串,所以需要反序列化
      return JSON.parse(res.data)
    }, err => {
      this.loading?.close()
      return err
    })
  }

  request(config: AxiosRequestConfig) {
    return this.instance.request(config)
  }
}

环境变量

在开发中,有时候我们需要根据不同的环境设置不同的环境变量,常见的有四种环境:

  • 开发环境: development
  • 生产环境: production
  • 测试环境: test
  • 预发布环境: stage

配置方式1: 手动的切换不同的环境(不推荐)

// 开发环境
// const BASE_URL = 'http://example.org/dev'
// const BASE_NAME = 'Klaus'

// 生产环境
// const BASE_URL = 'http://example.org/prod'
// const BASE_NAME = 'Alex'

// 测试环境
// const BASE_URL = 'http://example.org/test'
// const BASE_NAME = 'Steven'

配置方式2 --- 根据process.env.NODE_ENV的值进行区分

// vite默认会设置一下自带的环境变量
// 如  MODE, PROD, DEV, SSR, BASE_URL等
if (import.meta.env.MODE === 'development') {
 // ... do something
} else {
 // ... do else
}

配置方式3 --- 编写不同的环境变量配置文件

# .env.production
# 注意: 在vite中所有的环境变量必须以VITE_开头
VITE_APP_TITLE=My App in production
# .env.development
VITE_APP_TITLE=My App in development

vite在打包的时候,会自动根据开发环境注入不同的环境变量,我们可以读取这些环境变量并在需要的地方进行使用,如vite配置文件,src源代码中等等

// 使用
console.log(import.meta.env.VITE_APP_TITLE)

总结

到此这篇关于vue3实战教程之axios的封装和环境变量的文章就介绍到这了,更多相关vue3 axios封装和环境变量内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue3+TypeScript封装axios并进行请求调用的实现

    不是吧,不是吧,原来真的有人都2021年了,连TypeScript都没听说过吧?在项目中使用TypeScript虽然短期内会增加一些开发成本,但是对于其需要长期维护的项目,TypeScript能够减少其维护成本,使用TypeScript增加了代码的可读性和可维护性,且拥有较为活跃的社区,当居为大前端的趋势所在,那就开始淦起来吧~ 使用TypeScript封装基础axios库 代码如下: // http.ts import axios, { AxiosRequestConfig, AxiosRes

  • Vue3中使用typescript封装axios的实例详解

    这个axios封装,因为是用在vue3的demo里面的,为了方便,在vue3的配置里面按需加载element-plus 封装axios http.ts import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' import { IResponseData } from '@/types' import { ElMessage, ElLoading, ILoadingInstance

  • vue3实战教程之axios的封装和环境变量

    目录 axios 基本使用 配置 封装 请求时添加loading 环境变量 总结 axios axios: ajax i/o system. 一个可以同时在浏览器和node环境进行网络请求的第三方库 功能特点: 在浏览器中发送 XMLHttpRequests 请求 在 node.js 中发送 http请求 支持 Promise API 拦截请求和响应 转换请求和响应数据 等等 基本使用 get请求 // 导入的axios是一个实例对象 import axios from 'axios' // a

  • 掌握SQL Server实战教程之SQL Server的安装指南

    目录 前言 一. 数据库的介绍 1.1 数据库的分类 1.2 MS SQL介绍 二. MS SQL的安装 2.1 从网站下载安装包 2.2 开始安装 选择基本版本 2.3 安装SSMS 三. 连接数据库 3.1 数据库的连接 3.2 创建数据库 总结 前言 本文沐风晓月带你来了解一下sqlserver数据库的安装及简单使用,本文的主要任务: 安装SQL Server并能够成功的远程链接,然后执行几条简单的SQL语句进行测试即可 一. 数据库的介绍 1.1 数据库的分类 数据库的种类有很多,根据存

  • kotlin实战教程之lambda编程

    前言 ambda即lambda表达式,简称lambda.本质上是可以传递给其它函数的一小段代码.有了lambda,可以轻松地把通用代码结构抽取成库函数.lambda最常见的用途是和集合一起配合.kotlin甚至还拥有带接收者的lambda,这是一种特殊的lambda. 本文是对<<kotlin实战>>中 "lambda编程"一章的总结,主要记录了一些我认为比较重要的点 在kotlin中常见的lambda用法主要由以下几种: 与集合一起使用 lambda可以与任意

  • Vue.js教程之axios与网络传输的学习实践

    前言 在学习了之前的路由vue-router和状态管理vuex之后,就应该是网络交互了.就学习尤大推荐的axios了.刚好本人对网络请求这块除了会get.put.post和delete这四个方法之外知之甚少,刚好补全上. 注意:Vue官方推荐的网络通信库不再是vue-resource了,推荐使用axios. 为何放弃vue-resource? 尤大的原话: 最近团队讨论了一下,Ajax 本身跟 Vue 并没有什么需要特别整合的地方,使用 fetch polyfill 或是 axios.super

  • MySQL实战教程之Join语句执行流程

    目录 Join语句执行流程 一.Index Nested-Loop Join 二.Simple Nested-Loop Join 三.Block Nested-Loop Join 四.总结 Join语句执行流程 Hi,我是阿昌,今天学习记录的是关于Join语句执行流程的内容. 在实际生产中,关于 join 语句使用的问题,一般会集中在以下两类: 不让使用 join,使用 join 有什么问题呢? 如果有两个大小不同的表做 join,应该用哪个表做驱动表呢? 创建两个表 t1 和 t2 来说明.

  • spring boot实战教程之shiro session过期时间详解

    前言 众所周知在spring boot内,设置session过期时间只需在application.properties内添加server.session.timeout配置即可.在整合shiro时发现,server.session.timeout设置为7200,但未到2小时就需要重新登录,后来发现是shiro的session已经过期了,shiro的session过期时间并不和server.session.timeout一致,目前是采用filter的方式来进行设置. ShiroSessionFil

  • vue3实战-axios请求封装问题(get、post、put、delete)

    目录 vue3实战axios请求封装问题 vue3 axios简易封装教程 总结 vue3实战axios请求封装问题 1.在src目录下创建http文件夹,在http文件夹下分别创建index.js.request.js.api.js 2.index.js的作用:用于导出api.js定义的所有接口,代码如下 export * from './api'; 3.request.js代码如下: import axios from 'axios'; import buildURL from 'axios

  • Vue3全局挂载使用Axios学习实战

    目录 引言 一.全局挂载 二.全局使用 引言 在vue2中会习惯性的把axios挂载到全局,以方便在各个组件或页面中使用this.$http请求接口.但是在vue3中取消了Vue.prototype,在全局挂载方法和属性时,需要使用官方提供的globalPropertiesAPI. 一.全局挂载 在vue2项目中,入口文件main.js配置Vue.prototype挂载全局方法对象: import Vue from 'vue' import router from '@/router' impo

  • ES6学习教程之Promise用法详解

    前言 promise用了这么多年了,一直也没有系统整理过.今天整理整理promise的相关东西,感兴趣的可以一起看一看.我尽量用更容易理解的语言来剖析一下promise 我准备分两篇文章来说明一下promise 一篇来理解和使用promise(本篇) 另一篇来从promise使用功能的角度来剖析下promise的源码(下一篇) 1.什么是Promise 我的理解是:实现让我们用同步的方式去写异步代码的一种技术.是异步解决方案的一种. 他可以将多个异步操作进行队列化,让它们可以按照我们的想法去顺序

  • WebGL学习教程之Three.js学习笔记(第一篇)

    webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染. WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏. 原生的WebGl比较复杂,主要通过对顶点着色器和片元着色器的操作,来实现渲染,但实现起来比较复杂,需要一定的数学基础,但更多的是需要学习

随机推荐