前言
在做vue中大型項(xiàng)目的時(shí)候,官方推薦使用axios用狱,但是原生的axios可能對(duì)項(xiàng)目的適配不友好运怖,所以,在工程開始的來(lái)封裝一下axios夏伊,保持全項(xiàng)目數(shù)據(jù)處理的統(tǒng)一性摇展。此文主要講在vue-cil項(xiàng)目中如何封裝axios,封裝請(qǐng)求溺忧,封裝公共的api咏连,頁(yè)面如何調(diào)用請(qǐng)求。
如果你能看到這篇文章鲁森,鑒于有很多小白可能會(huì)參考我這篇文章來(lái)進(jìn)行前期配置祟滴,特說(shuō)明下正式配置路線:
1.拿到項(xiàng)目及后臺(tái)接口,首先做的是配置全局代理及第二點(diǎn)歌溉;
2. 全局封裝axios及第三點(diǎn)request.js垄懂;
3.過(guò)濾axios請(qǐng)求方式,控制路徑及參數(shù)的格式及第四點(diǎn)http.js;
4.正式封裝api及第五點(diǎn)api.js埠偿;
5.頁(yè)面調(diào)用;
正文
一榜晦、vue項(xiàng)目的前期配置
新建vue項(xiàng)目冠蒋,下載axios,并在main.js中導(dǎo)入axios
npm i axios -S
//main.js
import axios from "axios";
二乾胶、配置config文件中的代理地址
在項(xiàng)目config目錄下的修改 index.js文件抖剿,這里是主要書寫配置多個(gè)后臺(tái)接口。關(guān)于代理可能出現(xiàn)的問(wèn)題识窿,可以查看我的另一篇文檔VueCil代理本地proxytable報(bào)錯(cuò)的解析斩郎;
vue cil2舊版本的代理配置——config/index.js
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
// 后端請(qǐng)求地址代理,配置后testIp再之后的頁(yè)面調(diào)用時(shí)就直接指代 http://197.82.15.15:8088
proxyTable: {
'/testIp': {
target: 'http://197.82.15.15:8088',
changeOrigin: true,
pathRewrite: {
'^/testIp': ''
}
},
'/elseIp': {
target: 'http://182.83.19.15:8080',
changeOrigin: true,
pathRewrite: {
'^/esleIp': ''
}
},
},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
vuecil 3+ 新版本的代理配置–vue.config.js 文件
關(guān)于多代理配置:
devServer: {
overlay: { // 讓瀏覽器 overlay 同時(shí)顯示警告和錯(cuò)誤
warnings: true,
errors: true
},
host: "localhost",
port: 8080, // 端口號(hào)
https: false, // https:{type:Boolean}
open: false, //配置后自動(dòng)啟動(dòng)瀏覽器
hotOnly: true, // 熱更新
// proxy: 'http://localhost:8080' // 配置跨域處理,只有一個(gè)代理
proxy: { //配置多個(gè)代理
"/testIp": {
target: "http://197.0.0.1:8088",
changeOrigin: true,
ws: true,//websocket支持
secure: false,
pathRewrite: {
"^/testIp": "/"
}
},
"/elseIp": {
target: "http://197.0.0.2:8088",
changeOrigin: true,
//ws: true,//websocket支持
secure: false,
pathRewrite: {
"^/elseIp": "/"
}
},
}
}
如果有多后臺(tái)喻频,就可以在api文件夾下另外新建一個(gè)elseApi.js 缩宜,書寫當(dāng)前ip下的接口請(qǐng)求。方法同上甥温,只是 let resquest = "/elseIp/request/" 調(diào)用的時(shí)候把端口更改一下锻煌。
三、封裝axios實(shí)例 —— request.js
在項(xiàng)目src目錄下新建utils文件夾姻蚓,然后在其中新建 request.js文件宋梧,這個(gè)文件是主要書寫axios的封裝過(guò)程。
/**** request.js ****/
// 導(dǎo)入axios
import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message} from 'element-ui';
//1. 創(chuàng)建新的axios實(shí)例狰挡,
const service = axios.create({
// 公共接口--這里注意后面會(huì)講
baseURL: process.env.BASE_API,
// 超時(shí)時(shí)間 單位是ms捂龄,這里設(shè)置了3s的超時(shí)時(shí)間
timeout: 3 * 1000
})
// 2.請(qǐng)求攔截器
service.interceptors.request.use(config => {
//發(fā)請(qǐng)求前做的一些處理,數(shù)據(jù)轉(zhuǎn)化加叁,配置請(qǐng)求頭倦沧,設(shè)置token,設(shè)置loading等,根據(jù)需求去添加
config.data = JSON.stringify(config.data); //數(shù)據(jù)轉(zhuǎn)化,也可以使用qs轉(zhuǎn)換
config.headers = {
'Content-Type':'application/x-www-form-urlencoded' //配置請(qǐng)求頭
}
//注意使用token的時(shí)候需要引入cookie方法或者用本地localStorage等方法它匕,推薦js-cookie
const token = getCookie('名稱');//這里取token之前刀脏,你肯定需要先拿到token,存一下
if(token){
config.params = {'token':token} //如果要求攜帶在參數(shù)中
config.headers.token= token; //如果要求攜帶在請(qǐng)求頭中
}
return config
}, error => {
Promise.reject(error)
})
// 3.響應(yīng)攔截器
service.interceptors.response.use(response => {
//接收到響應(yīng)數(shù)據(jù)并成功后的一些共有的處理,關(guān)閉loading等
return response
}, error => {
/***** 接收到異常響應(yīng)的處理開始 *****/
if (error && error.response) {
// 1.公共錯(cuò)誤處理
// 2.根據(jù)響應(yīng)碼具體處理
switch (error.response.status) {
case 400:
error.message = '錯(cuò)誤請(qǐng)求'
break;
case 401:
error.message = '未授權(quán)超凳,請(qǐng)重新登錄'
break;
case 403:
error.message = '拒絕訪問(wèn)'
break;
case 404:
error.message = '請(qǐng)求錯(cuò)誤,未找到該資源'
window.location.href = "/NotFound"
break;
case 405:
error.message = '請(qǐng)求方法未允許'
break;
case 408:
error.message = '請(qǐng)求超時(shí)'
break;
case 500:
error.message = '服務(wù)器端出錯(cuò)'
break;
case 501:
error.message = '網(wǎng)絡(luò)未實(shí)現(xiàn)'
break;
case 502:
error.message = '網(wǎng)絡(luò)錯(cuò)誤'
break;
case 503:
error.message = '服務(wù)不可用'
break;
case 504:
error.message = '網(wǎng)絡(luò)超時(shí)'
break;
case 505:
error.message = 'http版本不支持該請(qǐng)求'
break;
default:
error.message = `連接錯(cuò)誤${error.response.status}`
}
} else {
// 超時(shí)處理
if (JSON.stringify(error).includes('timeout')) {
Message.error('服務(wù)器響應(yīng)超時(shí)愈污,請(qǐng)刷新當(dāng)前頁(yè)')
}
error.message = '連接服務(wù)器失敗'
}
Message.error(error.message)
/***** 處理結(jié)束 *****/
//如果不需要錯(cuò)誤處理,以上的處理過(guò)程都可省略
return Promise.resolve(error.response)
})
//4.導(dǎo)入文件
export default service
特殊說(shuō)明:
鑒于有很多朋友問(wèn)關(guān)于數(shù)據(jù)轉(zhuǎn)換這塊的問(wèn)題轮傍,特在頁(yè)面中單獨(dú)回復(fù)一下暂雹!
config.data = JSON.stringify(config.data);
config.headers = { 'Content-Type':'application/x-www-form-urlencoded' }
const token = getCookie('名稱')
if(token){
config.params = {'token':token} ;
config.headers.token= token;
}
上述的代碼都是請(qǐng)求的配置項(xiàng),非必須创夜,也是分情況的杭跪,data/headers /params 這種本身的參數(shù)都有多種,和后臺(tái)溝通,需要什么就配什么涧尿!
config.data = JSON.stringify(config.data);為什么不用qs.stringify系奉,因?yàn)槲业暮笈_(tái)想要的只是json類型的傳參,而qs轉(zhuǎn)換會(huì)轉(zhuǎn)換成為鍵值對(duì)拼接的字符串形式姑廉。當(dāng)然你們后臺(tái)需要傳遞字符串類型參數(shù)缺亮,那就換成qs或者其他格式方式。
const token = getCookie('名稱')這是token的取值桥言,在取之前你肯定需要發(fā)請(qǐng)求拿到token萌踱,然后setCookie存起來(lái),而名稱就是你存的token的名稱号阿,每個(gè)人的不一樣并鸵;
config.headers = { 'Content-Type':'application/x-www-form-urlencoded' }請(qǐng)求頭內(nèi)容的配置,也是不同的扔涧,application/x-www-form-urlencoded :form表單數(shù)據(jù)被編碼為key/value格式發(fā)送到服務(wù)器(表單默認(rèn)的提交數(shù)據(jù)的格式)园担,你可以根據(jù)實(shí)際情況去配置自己需要的;
以上
我已經(jīng)舉了很清晰的例子枯夜,寫代碼的過(guò)程是自己動(dòng)腦去搭建工程的粉铐,希望能看到我文章的各位,善于搜索卤档,善于思考蝙泼,善于總結(jié);
當(dāng)然我很喜歡幫大家解決問(wèn)題劝枣,但是相關(guān)的基礎(chǔ)問(wèn)題汤踏,還是建議自己去學(xué)習(xí)掌握。
四舔腾、封裝請(qǐng)求——http.js
在項(xiàng)目src目錄下的utils文件夾中新建 http.js文件溪胶,這個(gè)文件是主要書寫幾種請(qǐng)求的封裝過(guò)程。
/**** http.js ****/
// 導(dǎo)入封裝好的axios實(shí)例
import request from './request'
const http ={
/**
* methods: 請(qǐng)求
* @param url 請(qǐng)求地址
* @param params 請(qǐng)求參數(shù)
*/
get(url,params){
const config = {
method: 'get',
url:url
}
if(params) config.params = params
return request(config)
},
post(url,params){
const config = {
method: 'post',
url:url
}
if(params) config.data = params
return request(config)
},
put(url,params){
const config = {
method: 'put',
url:url
}
if(params) config.params = params
return request(config)
},
delete(url,params){
const config = {
method: 'delete',
url:url
}
if(params) config.params = params
return request(config)
}
}
//導(dǎo)出
export default http
五稳诚、正式封裝API哗脖,用于發(fā)送請(qǐng)求——api.js
在項(xiàng)目src目錄下新建api文件夾,然后在其中新建 api.js文件扳还,這個(gè)文件是主要書寫API的封裝過(guò)程才避。
寫法一:適合分類導(dǎo)出
import http from '../utils/http'
//
/**
* @parms resquest 請(qǐng)求地址 例如:http://197.82.15.15:8088/request/...
* @param '/testIp'代表vue-cil中config,index.js中配置的代理
*/
let resquest = "/testIp/request/"
// get請(qǐng)求
export function getListAPI(params){
return http.get(`${resquest}/getList.json`,params)
}
// post請(qǐng)求
export function postFormAPI(params){
return http.post(`${resquest}/postForm.json`,params)
}
// put 請(qǐng)求
export function putSomeAPI(params){
return http.put(`${resquest}/putSome.json`,params)
}
// delete 請(qǐng)求
export function deleteListAPI(params){
return http.delete(`${resquest}/deleteList.json`,params)
}
寫法二:使用全部導(dǎo)出
import http from '../utils/http'
//
/**
* @parms resquest 請(qǐng)求地址 例如:http://197.82.15.15:8088/request/...
* @param '/testIp'代表vue-cil中config氨距,index.js中配置的代理
*/
let resquest = "/testIp/request/"
// get請(qǐng)求
export default{
getListAPI(params){
return http.get(`${resquest}/getList.json`,params)
},
postFormAPI(params){
return http.post(`${resquest}/postForm.json`,params)
}
}
注意:一個(gè)項(xiàng)目中如果后臺(tái)請(qǐng)求不是同一個(gè)ip桑逝,而是多個(gè)ip的時(shí)候,可以在api文件夾下建立多個(gè)js俏让,用來(lái)調(diào)用請(qǐng)求楞遏。
我們看下之前遺留的一個(gè)問(wèn)題:
//創(chuàng)建新的axios實(shí)例茬暇,
const service = axios.create({
baseURL: process.env.BASE_API,
timeout: 3 * 1000
})
在之前封裝公共接口的baseUrl時(shí)候,用了webpack中的全局變量process.env.BASE_API寡喝,而不是直接寫死ip糙俗,也是為了適應(yīng)多個(gè)后臺(tái)或者開發(fā)的時(shí)候的api地址和發(fā)布的時(shí)候的api地址不一樣這種情況。
以上 關(guān)于配置環(huán)境 和接口 基本搭建完畢预鬓,下面看一下調(diào)用:
六巧骚、如何在vue文件中調(diào)用
方法一:用到哪個(gè)api 就調(diào)用哪個(gè)接口——適用于上文接口分類導(dǎo)出;
import {getListAPI,postFormAPI, putSomeAPI, deleteListAPI} from '@/api/api'
methods: {
//promise調(diào)用珊皿,鏈?zhǔn)秸{(diào)用, getList()括號(hào)內(nèi)只接受參數(shù)巨税;
// get不傳參
getList() {
getListAPI().then(res => console.log(res)).catch(err => console.log(err))
},
//post傳參
postForm(formData) {
let data = formData
postFormAPI(data).then(res => console.log(res)).catch(err => console.log(err))
},
//async await同步調(diào)用
async postForm(formData) {
const postRes = await postFormAPI(formData)
const putRes = await putSomeAPI({data: 'putTest'})
const deleteRes = await deleteListAPI(formData.name)
// 數(shù)據(jù)處理
console.log(postRes);
console.log(putRes);
console.log(deleteRes);
},
}
方法二 :把a(bǔ)pi全部導(dǎo)入蟋定,然后用哪個(gè)調(diào)用哪個(gè)api——適用于全部導(dǎo)出
import api from '@/api/api'
methods: {
getList() {
api.getListAPI(data).then(res => {
//數(shù)據(jù)處理
}).catch(err => console.log(err))
}
}
結(jié)語(yǔ)
以上就詳細(xì)介紹了,在vue-cil項(xiàng)目中 如何封裝axios草添,封裝請(qǐng)求驶兜,封裝公共的api,配置多個(gè)接口远寸,頁(yè)面如何調(diào)用請(qǐng)求等問(wèn)題抄淑,都是親測(cè)有用的~ 但是這種封裝方法的話,更適合大中型項(xiàng)目驰后,配置比較合理肆资,如果是自己小項(xiàng)目,就直接用axios就完事了灶芝。郑原。。
補(bǔ)充:
- 關(guān)于代理的配置及若出現(xiàn)配置代理報(bào)錯(cuò)404的問(wèn)題夜涕,可以參考我的文章:代理的配置來(lái)解決犯犁;