1.目录层级

src目录下分为5个文件夹。这里做简单处理,其中axios请求主要体现在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拦截器

拦截器主要包含请求拦截器和响应拦截器,在请求拦截器中可以设置token,cookie,可以在请求头中进行各种操作

//interceptors.ts
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import service from "./srevice";
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    //给请求头设置token
    // if (token) {
    //   config.headers!.Authorization = `baseUrl ${token}`;
    // }
    return config;
  },
  (error: AxiosError) => {
    ElMessage.error(error.message);
    return Promise.reject(error);
  }
);
/* 响应拦截器 */
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const { code, message, data } = response.data; // 根据自定义错误码判断请求是否成功
    if (code === 0) {
      // 将组件用的数据返回
      return data;
    } else {
      // 处理业务错误。
      ElMessage.error(message);
      return Promise.reject(new Error(message));
    }
  },
  (error: AxiosError) => {
    // 处理 HTTP 网络错误
    let message = "";
    // HTTP 状态码
    const status = error.response?.status;
    switch (status) {
      case 401:
        message = "token失效,请重新登录";
        // 这里可以触发退出的 action
        break;
      case 403:
        message = "没有权限,请获取权限后登录";
        break;
      case 404:
        message = "页面不存在";
        break;
      case 500:
        message = "服务器故障";
        break;
      case 502:
        message = "数据库查询错误";
        break;
      default:
        message = "网络连接错误";
    }
    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请求,在这里我是根据页面模块功能进行划分,如home页面所有请求就在home文件下,shop所有请求都在shop文件夹下,在index.ts中进行引入,并导出,这么做的好处是我们日常开发中很容易根据页面模块去找到对应的请求,协同开发中也不容易导致请求接口混乱

3.1细分功能模块

//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进行统一模块化管理,跟api层类似,分页面模块进行分层

//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的原型上,因此需要调用它的一个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();
//发送请求
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写的简单服务,这里简单做了路由层和请求serve层

db是数据源,因为没有引入sql数据库,所以这里使用node简单对json数据文件进行读写操作满足简单的增删改查操作,palyData用于操作数据json

6.1 express搭建本地服务

//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端口服务启动')
})

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.总结

这篇文章主要是对axios的ts封装进行简单的探究,因为没有后端代码,没办法进行测试,因此使用了node,使用express框架搭建了一个本地服务。日常开发中封装不仅仅是为了图一时的方便简单,好的封装代码层级结构也会方便项目后期的迭代化,避免到了项目后期,项目代码变得臃肿而繁琐,我觉得优秀的代码不是写出来别人看不懂,一目了然的代码才是好的代码

以上就是vue3 typescript封装axios过程示例的详细内容,更多关于vue3 typescript封装axios的资料请关注Devmax其它相关文章!

vue3 typescript封装axios过程示例的更多相关文章

  1. vue3获取当前路由地址

    本文详细讲解了vue3获取当前路由地址的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 十分钟带你快速上手Vue3过渡动画

    在开发中我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验,下面这篇文章主要给大家介绍了关于如何快速上手Vue3过渡动画的相关资料,需要的朋友可以参考下

  3. 用vue3封装一个符合思维且简单实用的弹出层

    最近新项目中需要一个弹窗组件,所以我就做了一个,下面这篇文章主要给大家介绍了关于如何利用vue3封装一个符合思维且简单实用的弹出层,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  4. 使用Vite+Vue3+Vant全家桶快速构建项目步骤详解

    这篇文章主要为大家介绍了使用Vite+Vue3+Vant全家桶快速构建项目步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  5. vue3中$attrs的变化与inheritAttrs的使用详解

    $attrs现在包括class和style属性。 也就是说在vue3中$listeners不存在了,vue2中$listeners是单独存在的,在vue3 $attrs包括class和style属性, vue2中 $attrs 不包含class和style属性,这篇文章主要介绍了vue3中$attrs的变化与inheritAttrs的使用 ,需要的朋友可以参考下

  6. vue3中proxy的基本用法说明

    这篇文章主要介绍了vue3中proxy的基本用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. 使用typescript类型实现ThreeSum

    这篇文章主要介绍了使用typescript类型实现ThreeSum,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以一下,希望对你学习又是帮助

  8.  typeScript入门基础介绍

    这篇文章主要介绍了 typeScript入门基础,TypeScript 是由微软开发的开源、跨平台的编程语言,是 javaScript 的超集,最终被编译为 javaScript代码。常常被简称为TS支持JS、ES语法,下文将继续其他基础介绍,需要的朋友可以参考一下

  9. typescript返回值类型和参数类型的具体使用

    本文主要介绍了typescript返回值类型和参数类型的具体使用文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  10. Node.js中对通用模块的封装方法

    这篇文章主要介绍了Node.js中对通用模块的封装方法,封装方法参考了Underscore.js的实现,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部