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

src目錄下分為5個(gè)文件夾。這里做簡單處理,其中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ù)自定義錯(cuò)誤碼判斷請求是否成功
if (code === 0) {
// 將組件用的數(shù)據(jù)返回
return data;
} else {
// 處理業(yè)務(wù)錯(cuò)誤。
ElMessage.error(message);
return Promise.reject(new Error(message));
}
},
(error: AxiosError) => {
// 處理 HTTP 網(wǎng)絡(luò)錯(cuò)誤
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ù)庫查詢錯(cuò)誤";
break;
default:
message = "網(wǎng)絡(luò)連接錯(cuò)誤";
}
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層
這個(gè)層級主要是對接口中的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)用它的一個(gè)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);
};
//點(diǎn)擊事件
const getList = (): void => {
getTreeList();
};
</script>
<template>
<el-button type="primary" @click="getList">點(diǎn)擊</el-button>
</template>
<style scoped>
</style>
6.后端接口
這里的請求后端是我用express寫的簡單服務(wù),這里簡單做了路由層和請求serve層

db是數(shù)據(jù)源,因?yàn)闆]有引入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)行簡單的探究,因?yàn)闆]有后端代碼,沒辦法進(jìn)行測試,因此使用了node,使用express框架搭建了一個(gè)本地服務(wù)。日常開發(fā)中封裝不僅僅是為了圖一時(shí)的方便簡單,好的封裝代碼層級結(jié)構(gòu)也會方便項(xiàng)目后期的迭代化,避免到了項(xiàng)目后期,項(xiàng)目代碼變得臃腫而繁瑣,我覺得優(yōu)秀的代碼不是寫出來別人看不懂,一目了然的代碼才是好的代碼
以上就是vue3 typescript封裝axios過程示例的詳細(xì)內(nèi)容,更多關(guān)于vue3 typescript封裝axios的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實(shí)現(xiàn)圖片路徑轉(zhuǎn)二進(jìn)制文件流(binary)
這篇文章主要介紹了vue實(shí)現(xiàn)圖片路徑轉(zhuǎn)二進(jìn)制文件流(binary),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
vue-seamless-scroll 實(shí)現(xiàn)簡單自動無縫滾動且添加對應(yīng)點(diǎn)擊事件的簡單整理
vue-seamless-scroll是一個(gè)基于Vue.js的簡單無縫滾動組件, 基于requestAnimationFrame實(shí)現(xiàn),配置多滿足多樣需求,目前支持上下左右無縫滾動,單步滾動,及支持水平方向的手動切換功能,本節(jié)介紹,vue添加 vue-seamless-scroll實(shí)現(xiàn)自動無縫滾動的效果,并對應(yīng)添加點(diǎn)擊事件2023-01-01
解決vue-router 二級導(dǎo)航默認(rèn)選中某一選項(xiàng)的問題
今天小編就為大家分享一篇解決vue-router 二級導(dǎo)航默認(rèn)選中某一選項(xiàng)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue 實(shí)現(xiàn)v-for循環(huán)回來的數(shù)據(jù)動態(tài)綁定id
今天小編就為大家分享一篇vue 實(shí)現(xiàn)v-for循環(huán)回來的數(shù)據(jù)動態(tài)綁定id,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue實(shí)現(xiàn)加載頁面自動觸發(fā)函數(shù)(及異步獲取數(shù)據(jù))
這篇文章主要介紹了vue實(shí)現(xiàn)加載頁面自動觸發(fā)函數(shù)(及異步獲取數(shù)據(jù)),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Vue 實(shí)現(xiàn)高級穿梭框 Transfer 封裝過程
本文介紹了基于Vue2和Element-UI實(shí)現(xiàn)的高級穿梭框組件Transfer的設(shè)計(jì)與技術(shù)方案,組件支持多項(xiàng)選擇,并能實(shí)時(shí)同步已選擇項(xiàng),包含豎版和橫版設(shè)計(jì)稿,并提供了組件的使用方法和源碼,此組件具備本地分頁和搜索功能,適用于需要在兩個(gè)列表間進(jìn)行數(shù)據(jù)選擇和同步的場景2024-09-09
vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式
這篇文章主要介紹了vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決
這篇文章主要介紹了Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

