vue3?typescript封裝axios過程示例
1.目錄層級(jí)
src目錄下分為5個(gè)文件夾。這里做簡(jiǎn)單處理,其中axios請(qǐng)求主要體現(xiàn)在api層,request層,config層和sevices層
2.request層
這里是封裝請(qǐng)求層,主要是使用axios的一些api封裝請(qǐng)求,我這里使用的是ts封裝
2.1請(qǐng)求主體
//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攔截器
攔截器主要包含請(qǐng)求攔截器和響應(yīng)攔截器,在請(qǐng)求攔截器中可以設(shè)置token,cookie,可以在請(qǐng)求頭中進(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) => { //給請(qǐng)求頭設(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ò)誤碼判斷請(qǐng)求是否成功 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失效,請(qǐng)重新登錄"; // 這里可以觸發(fā)退出的 action break; case 403: message = "沒有權(quán)限,請(qǐng)獲取權(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 封裝請(qǐng)求方法
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層
這一層級(jí)是為了封裝api請(qǐng)求,在這里我是根據(jù)頁面模塊功能進(jìn)行劃分,如home頁面所有請(qǐng)求就在home文件下,shop所有請(qǐng)求都在shop文件夾下,在index.ts中進(jìn)行引入,并導(dǎo)出,這么做的好處是我們?nèi)粘i_發(fā)中很容易根據(jù)頁面模塊去找到對(duì)應(yīng)的請(qǐng)求,協(xié)同開發(fā)中也不容易導(dǎo)致請(qǐng)求接口混亂
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è)層級(jí)主要是對(duì)接口中的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層請(qǐng)求掛載到全局中
在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ā)送請(qǐng)求 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.后端接口
這里的請(qǐng)求后端是我用express寫的簡(jiǎn)單服務(wù),這里簡(jiǎn)單做了路由層和請(qǐng)求serve層
db是數(shù)據(jù)源,因?yàn)闆]有引入sql數(shù)據(jù)庫,所以這里使用node簡(jiǎn)單對(duì)json數(shù)據(jù)文件進(jìn)行讀寫操作滿足簡(jiǎ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'); // 跨域允許的請(qǐng)求方式 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ù)啟動(dòng)') })
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é)
這篇文章主要是對(duì)axios的ts封裝進(jìn)行簡(jiǎn)單的探究,因?yàn)闆]有后端代碼,沒辦法進(jìn)行測(cè)試,因此使用了node,使用express框架搭建了一個(gè)本地服務(wù)。日常開發(fā)中封裝不僅僅是為了圖一時(shí)的方便簡(jiǎn)單,好的封裝代碼層級(jí)結(jié)構(gòu)也會(huì)方便項(xiàng)目后期的迭代化,避免到了項(xiàng)目后期,項(xiàng)目代碼變得臃腫而繁瑣,我覺得優(yōu)秀的代碼不是寫出來別人看不懂,一目了然的代碼才是好的代碼
以上就是vue3 typescript封裝axios過程示例的詳細(xì)內(nèi)容,更多關(guān)于vue3 typescript封裝axios的資料請(qǐng)關(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à)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06vue-seamless-scroll 實(shí)現(xiàn)簡(jiǎn)單自動(dòng)無縫滾動(dòng)且添加對(duì)應(yīng)點(diǎn)擊事件的簡(jiǎn)單整理
vue-seamless-scroll是一個(gè)基于Vue.js的簡(jiǎn)單無縫滾動(dòng)組件, 基于requestAnimationFrame實(shí)現(xiàn),配置多滿足多樣需求,目前支持上下左右無縫滾動(dòng),單步滾動(dòng),及支持水平方向的手動(dòng)切換功能,本節(jié)介紹,vue添加 vue-seamless-scroll實(shí)現(xiàn)自動(dòng)無縫滾動(dòng)的效果,并對(duì)應(yīng)添加點(diǎn)擊事件2023-01-01解決vue-router 二級(jí)導(dǎo)航默認(rèn)選中某一選項(xiàng)的問題
今天小編就為大家分享一篇解決vue-router 二級(jí)導(dǎo)航默認(rèn)選中某一選項(xiàng)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue 實(shí)現(xiàn)v-for循環(huán)回來的數(shù)據(jù)動(dòng)態(tài)綁定id
今天小編就為大家分享一篇vue 實(shí)現(xiàn)v-for循環(huán)回來的數(shù)據(jù)動(dòng)態(tài)綁定id,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue實(shí)現(xiàn)加載頁面自動(dòng)觸發(fā)函數(shù)(及異步獲取數(shù)據(jù))
這篇文章主要介紹了vue實(shí)現(xiàn)加載頁面自動(dòng)觸發(fā)函數(shù)(及異步獲取數(shù)據(jù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Vue 實(shí)現(xiàn)高級(jí)穿梭框 Transfer 封裝過程
本文介紹了基于Vue2和Element-UI實(shí)現(xiàn)的高級(jí)穿梭框組件Transfer的設(shè)計(jì)與技術(shù)方案,組件支持多項(xiàng)選擇,并能實(shí)時(shí)同步已選擇項(xiàng),包含豎版和橫版設(shè)計(jì)稿,并提供了組件的使用方法和源碼,此組件具備本地分頁和搜索功能,適用于需要在兩個(gè)列表間進(jìn)行數(shù)據(jù)選擇和同步的場(chǎng)景2024-09-09vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式
這篇文章主要介紹了vue跳轉(zhuǎn)頁面打開新窗口,并攜帶與接收參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決
這篇文章主要介紹了Vue引用第三方datepicker插件無法監(jiān)聽datepicker輸入框的值的解決,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01