vue3實戰(zhàn)教程之a(chǎn)xios的封裝和環(huán)境變量
axios
axios: ajax i/o system. 一個可以同時在瀏覽器和node環(huán)境進行網(wǎng)絡(luò)請求的第三方庫
功能特點:
- 在瀏覽器中發(fā)送 XMLHttpRequests 請求
- 在 node.js 中發(fā)送 http請求
- 支持 Promise API
- 攔截請求和響應(yīng)
- 轉(zhuǎn)換請求和響應(yīng)數(shù)據(jù)
- 等等
基本使用
get請求
// 導(dǎo)入的axios是一個實例對象
import axios from 'axios'
// axios方法返回的是promise
const res = await axios.get('https://httpbin.org/get', {
// 傳遞query參數(shù)
params: {
name: 'Klaus'
}
})
// 服務(wù)器實際返回的數(shù)據(jù)被放置在data屬性中
console.log(res.data)post請求
const res = await axios.post('https://httpbin.org/post', {
data: {
name: 'Klaus'
}
})request請求
// axios的所有請求本質(zhì)上都是在調(diào)用axios的request方法
const res = await axios.request({
url: 'https://httpbin.org/post',
method: 'post',
data: {
name: 'Klaus'
}
})all
axios.all本質(zhì)上就是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'
}
})
])攔截器
// 攔截器必須要在請求和響應(yīng)之前被注冊
// 請求攔截器 --- use方法的兩個參數(shù) --- 分別對應(yīng)resolve和reject
// resolve方法的參數(shù)為請求的配置選項
// reject方法的參數(shù)為錯誤對象
axios.interceptors.request.use(
config => {
console.log(config)
return config
},
err => console.error(err)
)
// 響應(yīng)攔截器 --- use方法的兩個參數(shù) --- 分別對應(yīng)resolve和reject
// resolve方法的參數(shù)為響應(yīng)體
// reject方法的參數(shù)為錯誤對象
axios.interceptors.response.use(
res => {
return res.data
},
err => console.error(err)
)配置
// 以下都是全局配置
// axios的所有全局配置都可以設(shè)置在屬性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)
})封裝
如果直接在每一個需要進行網(wǎng)絡(luò)請求的頁面中的引入axios會導(dǎo)致如下問題:
每一個頁面都需要引入axios, 就導(dǎo)致axios和邏輯的耦合性過強,如果以后需要進行修改,那么就需要去每一個使用了axios的頁面中進行修改
是十分麻煩且容易出錯的
在頁面請求的時候,我們會傳遞許多公共配置,例如BASE_URL,TOKEN等。
所以我們需要對我們的網(wǎng)絡(luò)請求進行二次封裝 --- 一般會放置在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
// 將一些相關(guān)配置配置成常量后在引入使用 // 將配置和調(diào)用解耦,如果需要修改,直接修改常量的值即可 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 apiapi.ts
import axios from 'axios'
import { ElLoading } from 'element-plus'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { Config } from './type'
// 導(dǎo)出的屬性和方法比較多 所以使用類來進行封裝
// 因為類具有比較好的封裝性
export default class {
instance: AxiosInstance
constructor(config: Config) {
// 每次創(chuàng)建實例的時候,都調(diào)用axios.create方法
// axios.create可以返回一個axios實例
// 這樣保證我們可以使用不同的配置創(chuàng)建多個axios實例
this.instance = axios.create(config)
// 如果存在實例級別的攔截器 就使用攔截器
// 這是針對于每一個請求特有的攔截器 --- 實例攔截
// 這里的操作也可以通過transformRequest和transformResponse配置項來進行實現(xiàn)
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)
}
// 這是所有實例共有的攔截器 --- 全局攔截
// 如果存在多個攔截器,那么多個攔截器都會被執(zhí)行
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) => {
// ?? --- 當(dāng)左側(cè)的操作數(shù)為 null 或者 undefined 時,返回右側(cè)操作數(shù),否則返回左側(cè)操作數(shù)
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 => {
// 關(guān)閉loading
this.loading?.close()
// axios返回的是字符串,所以需要反序列化
return JSON.parse(res.data)
}, err => {
this.loading?.close()
return err
})
}
request(config: AxiosRequestConfig) {
return this.instance.request(config)
}
}環(huán)境變量
在開發(fā)中,有時候我們需要根據(jù)不同的環(huán)境設(shè)置不同的環(huán)境變量,常見的有四種環(huán)境:
- 開發(fā)環(huán)境: development
- 生產(chǎn)環(huán)境: production
- 測試環(huán)境: test
- 預(yù)發(fā)布環(huán)境: stage
配置方式1: 手動的切換不同的環(huán)境(不推薦)
// 開發(fā)環(huán)境 // const BASE_URL = 'http://example.org/dev' // const BASE_NAME = 'Klaus' // 生產(chǎn)環(huán)境 // const BASE_URL = 'http://example.org/prod' // const BASE_NAME = 'Alex' // 測試環(huán)境 // const BASE_URL = 'http://example.org/test' // const BASE_NAME = 'Steven'
配置方式2 --- 根據(jù)process.env.NODE_ENV的值進行區(qū)分
// vite默認會設(shè)置一下自帶的環(huán)境變量
// 如 MODE, PROD, DEV, SSR, BASE_URL等
if (import.meta.env.MODE === 'development') {
// ... do something
} else {
// ... do else
}配置方式3 --- 編寫不同的環(huán)境變量配置文件
# .env.production # 注意: 在vite中所有的環(huán)境變量必須以VITE_開頭 VITE_APP_TITLE=My App in production
# .env.development VITE_APP_TITLE=My App in development
vite在打包的時候,會自動根據(jù)開發(fā)環(huán)境注入不同的環(huán)境變量,我們可以讀取這些環(huán)境變量并在需要的地方進行使用,如vite配置文件,src源代碼中等等
// 使用 console.log(import.meta.env.VITE_APP_TITLE)
總結(jié)
到此這篇關(guān)于vue3實戰(zhàn)教程之a(chǎn)xios的封裝和環(huán)境變量的文章就介紹到這了,更多相關(guān)vue3 axios封裝和環(huán)境變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入了解Vue3中偵聽器watcher的實現(xiàn)原理
在平時的開發(fā)工作中,我們經(jīng)常使用偵聽器幫助我們?nèi)ビ^察某個數(shù)據(jù)的變化然后去執(zhí)行一段邏輯。在?Vue.js?2.x?中,你可以通過?watch?選項去初始化一個偵聽器,稱作?watcher。本文將詳細為大家介紹一下偵聽器的實現(xiàn)原理,需要的可以參考一下2022-04-04
vue轉(zhuǎn)electron項目及解決使用fs報錯:Module?not?found:?Error:?Can&apo
這篇文章主要給大家介紹了關(guān)于vue轉(zhuǎn)electron項目及解決使用fs報錯:Module?not?found:?Error:?Can‘t?resolve?‘fs‘?in的相關(guān)資料,文中通過圖文以及實例代碼介紹的非常詳細,需要的朋友可以參考下2022-11-11
Vue實現(xiàn)Hover功能(mouseover與mouseenter的區(qū)別及說明)
這篇文章主要介紹了Vue實現(xiàn)Hover功能(mouseover與mouseenter的區(qū)別及說明),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
前端在el-dialog中嵌套多個el-dialog代碼實現(xiàn)
最近使用vue+elementUI做項目,使用過程中很多地方會用到dialog這個組件,有好幾個地方用到了dialog的嵌套,下面這篇文章主要給大家介紹了關(guān)于前端在el-dialog中嵌套多個el-dialog代碼實現(xiàn)的相關(guān)資料,需要的朋友可以參考下2024-01-01
Vue?中ref()和?reactive()響應(yīng)式數(shù)據(jù)的使用方法
article介紹Vue3中ref()和reactive()函數(shù)的使用方法,ref()用于創(chuàng)建基本數(shù)據(jù)類型的響應(yīng)式引用,reactive()用于創(chuàng)建響應(yīng)式對象,本文介紹Vue中ref()和reactive()響應(yīng)式數(shù)據(jù)的使用方法,感興趣的朋友一起看看吧2025-01-01

