vue3實(shí)戰(zhàn)教程之a(chǎn)xios的封裝和環(huán)境變量
axios
axios: ajax i/o system. 一個(gè)可以同時(shí)在瀏覽器和node環(huán)境進(jìn)行網(wǎng)絡(luò)請(qǐng)求的第三方庫(kù)
功能特點(diǎn):
- 在瀏覽器中發(fā)送 XMLHttpRequests 請(qǐng)求
- 在 node.js 中發(fā)送 http請(qǐng)求
- 支持 Promise API
- 攔截請(qǐng)求和響應(yīng)
- 轉(zhuǎn)換請(qǐng)求和響應(yīng)數(shù)據(jù)
- 等等
基本使用
get請(qǐng)求
// 導(dǎo)入的axios是一個(gè)實(shí)例對(duì)象 import axios from 'axios' // axios方法返回的是promise const res = await axios.get('https://httpbin.org/get', { // 傳遞query參數(shù) params: { name: 'Klaus' } }) // 服務(wù)器實(shí)際返回的數(shù)據(jù)被放置在data屬性中 console.log(res.data)
post請(qǐng)求
const res = await axios.post('https://httpbin.org/post', { data: { name: 'Klaus' } })
request請(qǐng)求
// axios的所有請(qǐng)求本質(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' } }) ])
攔截器
// 攔截器必須要在請(qǐng)求和響應(yīng)之前被注冊(cè) // 請(qǐng)求攔截器 --- use方法的兩個(gè)參數(shù) --- 分別對(duì)應(yīng)resolve和reject // resolve方法的參數(shù)為請(qǐng)求的配置選項(xiàng) // reject方法的參數(shù)為錯(cuò)誤對(duì)象 axios.interceptors.request.use( config => { console.log(config) return config }, err => console.error(err) ) // 響應(yīng)攔截器 --- use方法的兩個(gè)參數(shù) --- 分別對(duì)應(yīng)resolve和reject // resolve方法的參數(shù)為響應(yīng)體 // reject方法的參數(shù)為錯(cuò)誤對(duì)象 axios.interceptors.response.use( res => { return res.data }, err => console.error(err) )
配置
// 以下都是全局配置 // axios的所有全局配置都可以設(shè)置在屬性defaults下 // 基本請(qǐng)求公共路徑 axios.defaults.baseURL = 'http://httpbin.org' // 超時(shí)時(shí)間 axios.defaults.timeout = 10000 // 需要傳遞的自定義請(qǐng)求頭 axios.defaults.headers = {}
// 局部配置 axios .get('/get', { params: { name: 'Klaus', age: 18 }, // 局部配置可以覆蓋全局配置 timeout: 5000, headers: {} }) .then((res) => { console.log(res.data) })
封裝
如果直接在每一個(gè)需要進(jìn)行網(wǎng)絡(luò)請(qǐng)求的頁(yè)面中的引入axios會(huì)導(dǎo)致如下問(wèn)題:
每一個(gè)頁(yè)面都需要引入axios, 就導(dǎo)致axios和邏輯的耦合性過(guò)強(qiáng),如果以后需要進(jìn)行修改,那么就需要去每一個(gè)使用了axios的頁(yè)面中進(jìn)行修改
是十分麻煩且容易出錯(cuò)的
在頁(yè)面請(qǐng)求的時(shí)候,我們會(huì)傳遞許多公共配置,例如BASE_URL,TOKEN等。
所以我們需要對(duì)我們的網(wǎng)絡(luò)請(qǐng)求進(jìn)行二次封裝 --- 一般會(huì)放置在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, } // 通過(guò)接口繼承的方式擴(kuò)展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, // 不同的實(shí)例可能有不同的攔截器 // 所以我們將攔截器封裝成一個(gè)擴(kuò)展屬性進(jìn)行傳入 // interceptor: { // requestInterceptor: config => { // console.log('請(qǐng)求成功') // 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' // 導(dǎo)出的屬性和方法比較多 所以使用類來(lái)進(jìn)行封裝 // 因?yàn)轭惥哂斜容^好的封裝性 export default class { instance: AxiosInstance constructor(config: Config) { // 每次創(chuàng)建實(shí)例的時(shí)候,都調(diào)用axios.create方法 // axios.create可以返回一個(gè)axios實(shí)例 // 這樣保證我們可以使用不同的配置創(chuàng)建多個(gè)axios實(shí)例 this.instance = axios.create(config) // 如果存在實(shí)例級(jí)別的攔截器 就使用攔截器 // 這是針對(duì)于每一個(gè)請(qǐng)求特有的攔截器 --- 實(shí)例攔截 // 這里的操作也可以通過(guò)transformRequest和transformResponse配置項(xiàng)來(lái)進(jìn)行實(shí)現(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) } // 這是所有實(shí)例共有的攔截器 --- 全局?jǐn)r截 // 如果存在多個(gè)攔截器,那么多個(gè)攔截器都會(huì)被執(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) } }
請(qǐng)求時(shí)添加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的樣式 // 所以需要自己手動(dòng)進(jìn)行引入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 時(shí),返回右側(cè)操作數(shù),否則返回左側(cè)操作數(shù) if (config?.showLoading ?? true) { // 開(kāi)啟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)境變量
在開(kāi)發(fā)中,有時(shí)候我們需要根據(jù)不同的環(huán)境設(shè)置不同的環(huán)境變量,常見(jiàn)的有四種環(huán)境:
- 開(kāi)發(fā)環(huán)境: development
- 生產(chǎn)環(huán)境: production
- 測(cè)試環(huán)境: test
- 預(yù)發(fā)布環(huán)境: stage
配置方式1: 手動(dòng)的切換不同的環(huán)境(不推薦)
// 開(kāi)發(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' // 測(cè)試環(huán)境 // const BASE_URL = 'http://example.org/test' // const BASE_NAME = 'Steven'
配置方式2 --- 根據(jù)process.env.NODE_ENV的值進(jìn)行區(qū)分
// vite默認(rèn)會(huì)設(shè)置一下自帶的環(huán)境變量 // 如 MODE, PROD, DEV, SSR, BASE_URL等 if (import.meta.env.MODE === 'development') { // ... do something } else { // ... do else }
配置方式3 --- 編寫(xiě)不同的環(huán)境變量配置文件
# .env.production # 注意: 在vite中所有的環(huán)境變量必須以VITE_開(kāi)頭 VITE_APP_TITLE=My App in production
# .env.development VITE_APP_TITLE=My App in development
vite在打包的時(shí)候,會(huì)自動(dòng)根據(jù)開(kāi)發(fā)環(huán)境注入不同的環(huán)境變量,我們可以讀取這些環(huán)境變量并在需要的地方進(jìn)行使用,如vite配置文件,src源代碼中等等
// 使用 console.log(import.meta.env.VITE_APP_TITLE)
總結(jié)
到此這篇關(guān)于vue3實(shí)戰(zhàn)教程之a(chǎn)xios的封裝和環(huán)境變量的文章就介紹到這了,更多相關(guān)vue3 axios封裝和環(huán)境變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于vue3使用particles粒子特效的問(wèn)題
這篇文章主要介紹了關(guān)于vue3使用particles粒子特效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06在vue.js中使用JSZip實(shí)現(xiàn)在前端解壓文件的方法
今天小編就為大家分享一篇在vue.js中使用JSZip實(shí)現(xiàn)在前端解壓文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09如何利用vue實(shí)現(xiàn)登陸界面及其跳轉(zhuǎn)詳解
在開(kāi)發(fā)中我們經(jīng)常遇到這樣的需求,需要用戶直接點(diǎn)擊一個(gè)鏈接進(jìn)入到一個(gè)頁(yè)面,下面這篇文章主要給大家介紹了關(guān)于如何利用vue實(shí)現(xiàn)登陸界面及其跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下2023-04-04Vue頁(yè)面監(jiān)聽(tīng)鍵盤(pán)按鍵的方法總結(jié)
在Vue頁(yè)面中,可以使用多種方法來(lái)監(jiān)聽(tīng)鍵盤(pán)按鍵,這篇文章主要為大家整理了五種常用的方法,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考下2023-10-10vue實(shí)現(xiàn)錄音并轉(zhuǎn)文字功能包括PC端web手機(jī)端web(實(shí)現(xiàn)過(guò)程)
vue實(shí)現(xiàn)錄音并轉(zhuǎn)文字功能,包括PC端,手機(jī)端和企業(yè)微信自建應(yīng)用端,本文通過(guò)實(shí)例代碼介紹vue實(shí)現(xiàn)錄音并轉(zhuǎn)文字功能包括PC端web手機(jī)端web,感興趣的朋友跟隨小編一起看看吧2024-08-08antd的select下拉框因?yàn)閿?shù)據(jù)量太大造成卡頓的解決方式
這篇文章主要介紹了antd的select下拉框因?yàn)閿?shù)據(jù)量太大造成卡頓的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決
這篇文章主要介紹了Vue3項(xiàng)目剛創(chuàng)建就報(bào)錯(cuò)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10