vue3?typescript封裝axios過程示例
1.目錄層級

src目錄下分為5個文件夾。這里做簡單處理,其中axios請求主要體現(xiàn)在api層,request層,config層和sevices層
2.request層
這里是封裝請求層,主要是使用axios的一些api封裝請求,我這里使用的是ts封裝
2.1請求主體
//services.ts
import axios from "axios";
import type {
AxiosInstance,
} from "axios";
const service: AxiosInstance = axios.create({
baseURL: "http://localhost:3000",
timeout: 5000,
});
export default service
2.2攔截器
攔截器主要包含請求攔截器和響應(yīng)攔截器,在請求攔截器中可以設(shè)置token,cookie,可以在請求頭中進(jìn)行各種操作
//interceptors.ts
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import service from "./srevice";
service.interceptors.request.use(
(config: AxiosRequestConfig) => {
//給請求頭設(shè)置token
// if (token) {
// config.headers!.Authorization = `baseUrl ${token}`;
// }
return config;
},
(error: AxiosError) => {
ElMessage.error(error.message);
return Promise.reject(error);
}
);
/* 響應(yīng)攔截器 */
service.interceptors.response.use(
(response: AxiosResponse) => {
const { code, message, data } = response.data; // 根據(jù)自定義錯誤碼判斷請求是否成功
if (code === 0) {
// 將組件用的數(shù)據(jù)返回
return data;
} else {
// 處理業(yè)務(wù)錯誤。
ElMessage.error(message);
return Promise.reject(new Error(message));
}
},
(error: AxiosError) => {
// 處理 HTTP 網(wǎng)絡(luò)錯誤
let message = "";
// HTTP 狀態(tài)碼
const status = error.response?.status;
switch (status) {
case 401:
message = "token失效,請重新登錄";
// 這里可以觸發(fā)退出的 action
break;
case 403:
message = "沒有權(quán)限,請獲取權(quán)限后登錄";
break;
case 404:
message = "頁面不存在";
break;
case 500:
message = "服務(wù)器故障";
break;
case 502:
message = "數(shù)據(jù)庫查詢錯誤";
break;
default:
message = "網(wǎng)絡(luò)連接錯誤";
}
ElMessage.error(message);
return Promise.reject(error);
}
);
export default service
2.3 封裝請求方法
import type {AxiosRequestConfig } from "axios";
import service from "./interceptors";
const httpObj = {
get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return service.get(url, config);
},
post<T = any>(
url: string,
data?: object,
config?: AxiosRequestConfig
): Promise<T> {
return service.post(url, data, config);
},
put<T = any>(
url: string,
data?: object,
config?: AxiosRequestConfig
): Promise<T> {
return service.put(url, data, config);
},
delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return service.delete(url, config);
},
};
export default httpObj;
3.api層
這一層級是為了封裝api請求,在這里我是根據(jù)頁面模塊功能進(jìn)行劃分,如home頁面所有請求就在home文件下,shop所有請求都在shop文件夾下,在index.ts中進(jìn)行引入,并導(dǎo)出,這么做的好處是我們?nèi)粘i_發(fā)中很容易根據(jù)頁面模塊去找到對應(yīng)的請求,協(xié)同開發(fā)中也不容易導(dǎo)致請求接口混亂

3.1細(xì)分功能模塊
//api/home/home.ts
import request from "../../request/index";
import services from "../../services/index";
let api = {
getTreeList: () => {
return request.get(services.treeUrl);
},
};
export default api;
3.2api層主體
//api/index.ts
import home from "./home/home"
let api = {
home: { ...home},
};
export default api;
4.service層
這個層級主要是對接口中的url進(jìn)行統(tǒng)一模塊化管理,跟api層類似,分頁面模塊進(jìn)行分層

//services/home/home.ts
interface urlType {
treeUrl: string;
}
const url:urlType = {
treeUrl: "/tree/getTreeList",
};
export default url
//services/index.ts
import home from "./home/home"
export default {
...home
}
5.將api層請求掛載到全局中
在vue3.0中不存在this,所以無法掛載this的原型上,因此需要調(diào)用它的一個api
//main.ts
import { createApp } from "vue";
import ElementPlus from "element-plus";
//引入elementui樣式
import 'element-plus/dist/index.css'
import App from "./App.vue";
//引入api層
import api from "./api/index";
const app = createApp(App);
//掛載api層
app.config.globalProperties.$api = api;
app.use(ElementPlus);
app.mount("#app");
在頁面中使用,新建view方頁面組件,components放公共組件,在view中添加home組件
//src/view/home.vue
<script setup lang="ts">
import { getCurrentInstance } from "vue";
//引入全局掛載變量
const { proxy }: any = getCurrentInstance();
//發(fā)送請求
const getTreeList = async (): Promise<void> => {
const data = await proxy.$api.home.getTreeList();
console.log(data);
};
//點擊事件
const getList = (): void => {
getTreeList();
};
</script>
<template>
<el-button type="primary" @click="getList">點擊</el-button>
</template>
<style scoped>
</style>
6.后端接口
這里的請求后端是我用express寫的簡單服務(wù),這里簡單做了路由層和請求serve層

db是數(shù)據(jù)源,因為沒有引入sql數(shù)據(jù)庫,所以這里使用node簡單對json數(shù)據(jù)文件進(jìn)行讀寫操作滿足簡單的增刪改查操作,palyData用于操作數(shù)據(jù)json
6.1 express搭建本地服務(wù)
//serve/index.js
const express = require('express')
const app = express()
const tree=require('./router/tree')
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin','*');
// 允許的header類型
res.header('Access-Control-Allow-Headers','content-type');
// 跨域允許的請求方式
res.header('Access-Control-Allow-Methods','DELETE,PUT,POST,GET,OPTIONS');
if (req.method === 'OPTIONS') {
return res.send()
}
next()
})
app.use('/tree',tree)
app.listen(3000, () => {
console.log('3000端口服務(wù)啟動')
})
6.2路由層封裝
//serve/route/tree.js
const express = require('express')
const { readFile,writeFile} =require('../playData/playData')
const router=express.Router()
router.get('/getTreeList', (req, res) => {
readFile((data) => {
res.json(data)
})
})
router.get('/deleteTreeList/:id', (req, res) => {
let id = parseInt(req.params.id)
readFile((data) => {
let {
parent,
children
} = data
const newParent = parent.filter(item => item.id !== id)
const newChildren = children.filter(item => item.id !== id)
data.parent = newParent;
data.children = newChildren;
let json = JSON.stringify(data)
let msg='刪除成功'
writeFile(json,res,msg)
})
})
router.post('/modifyTreeList', (req, res) => {
const {data}=req.body
let id=parseInt(data.id)
let name=data.name;
readFile((data) => {
let {
parent,
children
} = data
parent.forEach(item => {
if(item.id==id){
item.name=name
}
})
children.forEach(item => {
if(item.id==id){
item.name=name
}
})
data.parent = parent;
data.children = children;
let json = JSON.stringify(data)
let msg='修改成功'
writeFile(json,res,msg)
})
});
module.exports=router
6.3讀寫操作
//serve/playData/playData.js
const fs = require('fs')
const path = require('path')
const p=path.join(__dirname, '../db/index.json')
const readFile = (callBack) => {
fs.readFile(p, 'utf8', (err, data) => {
if (err) {
return
}
callBack && callBack(JSON.parse(data))
})
}
const writeFile=(json,res,msg)=>{
fs.writeFile(p, json, (err) => {
res.json({
msg
})
})
}
module.exports={
readFile,
writeFile
}
7.總結(jié)
這篇文章主要是對axios的ts封裝進(jìn)行簡單的探究,因為沒有后端代碼,沒辦法進(jìn)行測試,因此使用了node,使用express框架搭建了一個本地服務(wù)。日常開發(fā)中封裝不僅僅是為了圖一時的方便簡單,好的封裝代碼層級結(jié)構(gòu)也會方便項目后期的迭代化,避免到了項目后期,項目代碼變得臃腫而繁瑣,我覺得優(yōu)秀的代碼不是寫出來別人看不懂,一目了然的代碼才是好的代碼
以上就是vue3 typescript封裝axios過程示例的詳細(xì)內(nèi)容,更多關(guān)于vue3 typescript封裝axios的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue2.0基于vue-cli+webpack同級組件之間的通信教程(推薦)
下面小編就為大家?guī)硪黄猇ue2.0基于vue-cli+webpack同級組件之間的通信教程(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09

