為什么要對(duì)axios進(jìn)行封裝饰潜?
- 實(shí)際開發(fā)過(guò)程中,我們項(xiàng)目可能會(huì)有大量接口和簸,因此我們寫代碼的時(shí)候囊拜,如果不進(jìn)行封裝,則會(huì)產(chǎn)生大量冗余代碼比搭,比如
catch
,還有就是大量的接口也會(huì)造成后期維護(hù)的麻煩
封裝通常包含幾個(gè)部分
- API的封裝冠跷,便于后期統(tǒng)一維護(hù)管理。
不同類型的接口身诺,分門別類放入不同的文件進(jìn)行管理蜜托,然后把這些文件放入統(tǒng)一的文件夾里。例如霉赡,聯(lián)系人這個(gè)類型的接口橄务,我們就可以單獨(dú)放入一個(gè)文件,姑且命名為contactApi.js
const CONTACT_API = {
// 獲取聯(lián)系人列表
getContactList:{
method:'get',
url:'/contactList'
},
//新建聯(lián)系人 form-data
newContactForm:{
method:'post',
url:'/contact/new/form'
},
//新建聯(lián)系人 application/json
newContactJson: {
method: 'post',
url: '/contact/new/json'
},
//編輯聯(lián)系人
editContact:{
method:'put',
url:'/contact/edit'
},
//刪除聯(lián)系人
delContact:{
method: 'delete',
url: '/contact'
}
}
export default CONTACT_API
- 對(duì)axios進(jìn)行封裝
import axios from 'axios'
import service from './contactApi'
import { Toast } from 'vant'
let instance = axios.create({
baseURL:'http://localhost:9000/api',
timeout:1000
})
const Http = {}; //包裹請(qǐng)求方法的容器
// 對(duì) service 進(jìn)行循環(huán)遍歷輸出不同的請(qǐng)求方法穴亏,也就是遍歷 CONTACT_API
// 下邊會(huì)將 請(qǐng)求格式/參數(shù) 進(jìn)行統(tǒng)一為 params蜂挪,isFormData,config
for(let key in service){
let api = service[key] //api包含url method
Http[key] = async function(
//方法接受的參數(shù)
//參數(shù)1 --- 請(qǐng)求參數(shù)params
// get請(qǐng)求的話嗓化,參數(shù)放到URL上
// post棠涮、put、patch請(qǐng)求的話刺覆,對(duì)應(yīng)的參數(shù)是data
// delete請(qǐng)求的話严肪,默認(rèn)放在URL上(當(dāng)然也可以放在data)
params,
//參數(shù)2 --- isFormData 標(biāo)識(shí)是否是 form-data 請(qǐng)求,默認(rèn)不是
isFormData = false,
//參數(shù)3 --- config 配置參數(shù)谦屑,可以在這里設(shè)置 headers驳糯、params、data等
config = {}
){
//聲明新變量氢橙,判斷content-type是否是form-data時(shí)候的參數(shù)的轉(zhuǎn)換
let newParams = {}
// 判斷 content-type 是否是 form-data
if(params && isFormData){
newParams = new FormData() //創(chuàng)建一個(gè)form-data格式的對(duì)象
for(let i in params){
newParams.append(i,params[i])
}
}else{
//不是form-data
newParams = params
}
// 不同請(qǐng)求的判斷
let response = {}; //請(qǐng)求的返回值
if (api.method === 'post' || api.method === 'put' || api.method === 'patch'){
try{
response = await instance[api.method](api.url, newParams,config)
}catch(err){
response = err
}
} else if (api.method === 'get' || api.method === 'delete'){
config.params = newParams
try {
response = await instance[api.method](api.url, config)
} catch (err) {
response = err
}
}
return response //返回響應(yīng)值
}
}
//請(qǐng)求攔截器
instance.interceptors.request.use(
config => {
//發(fā)起請(qǐng)求前做什么
//加一個(gè)動(dòng)態(tài)更新提示
Toast({
duration: 0, // 持續(xù)展示 toast
forbidClick: true, //是否禁止背景點(diǎn)擊
message: '加載中...'
})
return config
},
() => {
//請(qǐng)求錯(cuò)誤
Toast.clear() //因?yàn)門oast是一直展示的酝枢,所以請(qǐng)求錯(cuò)誤時(shí)需要關(guān)掉toast
Toast('請(qǐng)求錯(cuò)誤,請(qǐng)稍后重試')
}
)
//響應(yīng)攔截器
instance.interceptors.response.use(
//響應(yīng)成功
res => {
Toast.clear()
return res.data
},
() => {
Toast.clear()
Toast('請(qǐng)求錯(cuò)誤悍手,請(qǐng)稍后重試')
}
)
export default Http
- 掛載到Vue原型上(main.js里操作),之所以要掛載帘睦,是為了不在每個(gè)頁(yè)面都進(jìn)行
import axios from 'axios'
這樣類似的操作了袍患,掛載之后,全局可用官脓。
- 改造聯(lián)系人代碼
<template>
<div class="home">
<!-- 聯(lián)系人列表 -->
<van-contact-list
:list="list"
@add="onAdd"
@edit="onEdit"
/>
<!-- 聯(lián)系人編輯-->
<van-popup v-model="showEdit" position="bottom">
<van-contact-edit
:contact-info="editingContact"
:is-edit="isEdit"
@save="onSave"
@delete="onDelete"
/>
</van-popup>
</div>
</template>
<script>
import axios from 'axios'
import { ContactList,ContactEdit,Toast,Popup} from 'vant';
export default {
name: 'ContactList',
components:{
[ContactList.name]:ContactList,
[ContactEdit.name]:ContactEdit,
[Popup.name]:Popup
},
data(){
return {
// {
// id:'',
// name:'',
// tel:''
// }
list:[],
instance:null, //axios實(shí)例
showEdit:false, //編輯彈窗的顯隱
editingContact:{}, //正在編輯的聯(lián)系人數(shù)據(jù)
isEdit:false, //新建或編輯
}
},
created(){
this.instance = axios.create({
baseURL:'http://localhost:9000/api',
timeout:1000
})
this.getContactList()
},
methods:{
//獲取聯(lián)系人列表(改造后)
async getContactList(){
let res = await this.$Http.getContactList()
this.list = res.data
},
//添加聯(lián)系人
onAdd(){
this.showEdit = true
this.isEdit = false
},
//編輯聯(lián)系人
onEdit(info){
this.showEdit = true
this.isEdit = true
this.editingContact = info
},
//保存聯(lián)系人
async onSave(info){
if(this.isEdit){
//編輯保存
let res = await this.$Http.editContact(info)
if(res.code == 200){
Toast('編輯成功')
this.showEdit = false
this.getContactList()
}
}else{
//新建保存
//傳的3個(gè)參數(shù)协怒,第二個(gè)應(yīng)該傳false,因?yàn)槟J(rèn)是false,所以可以不寫,config也不需要傳
let res = await this.$Http.newContactJson(info)
if(res.code == 200){
Toast('新建成功')
this.showEdit = false
this.getContactList()
}
//form-data格式
// let res = await this.$Http.newContactForm(info,true)
// if(res.code == 200){
// Toast('新建成功')
// this.showEdit = false
// this.getContactList()
// }
}
},
//刪除聯(lián)系人人
async onDelete(info){
let res = await this.$Http.delContact({
id:info.id
})
if(res.code == 200){
Toast('刪除成功')
this.showEdit = false
this.getContactList()
}
}
}
}
</script>
<style scoped>
.van-popup {
height:40%
}
</style>