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); }; //點(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框架搭建了一個本地服務(wù)。日常開發(fā)中封裝不僅僅是為了圖一時的方便簡單,好的封裝代碼層級結(jié)構(gòu)也會方便項目后期的迭代化,避免到了項目后期,項目代碼變得臃腫而繁瑣,我覺得優(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),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06vue-seamless-scroll 實(shí)現(xiàn)簡單自動無縫滾動且添加對應(yīng)點(diǎn)擊事件的簡單整理
vue-seamless-scroll是一個基于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)選中某一選項的問題
今天小編就為大家分享一篇解決vue-router 二級導(dǎo)航默認(rèn)選中某一選項的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue 實(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,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue實(shí)現(xiàn)加載頁面自動觸發(fā)函數(shù)(及異步獲取數(shù)據(jù))
這篇文章主要介紹了vue實(shí)現(xiàn)加載頁面自動觸發(fā)函數(shù)(及異步獲取數(shù)據(jù)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07Vue 實(shí)現(xiàn)高級穿梭框 Transfer 封裝過程
本文介紹了基于Vue2和Element-UI實(shí)現(xiàn)的高級穿梭框組件Transfer的設(shè)計與技術(shù)方案,組件支持多項選擇,并能實(shí)時同步已選擇項,包含豎版和橫版設(shè)計稿,并提供了組件的使用方法和源碼,此組件具備本地分頁和搜索功能,適用于需要在兩個列表間進(jìn)行數(shù)據(jù)選擇和同步的場景2024-09-09vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式
這篇文章主要介紹了vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決
這篇文章主要介紹了Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01