0

0

vue3和ts封装axios及使用mock.js的方法是什么

王林

王林

发布时间:2023-05-18 10:22:14

|

1119人浏览过

|

来源于亿速云

转载

    前言

    我们要注意区分 axios 和 ajax :

    Ajax 是一种技术统称,技术内容包括:HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest,用于浏览器与服务器之间使用异步数据传输(HTTP 请求),做到局部请求以实现局部刷新,使用是基于 XMLHttpRequest 进行使用;

    Axios 是 一个基于 promise 的 HTTP 库,是一个是第三方库

    主要技术栈:vue3,ts,axios,mock.js,elementPlus

    一、axios 的依赖安装与处理  

    1. 依赖安装

    使用异步网络请求肯定离不开loading、message 等提示,今天我们配合 elementPlus 一起使用;

    立即学习前端免费学习笔记(深入)”;

    // 安装axios 
    npm install axios --save
     
    // 安装 elementPlus
    npm install element-plus --save

    2. 全局 axios 封装

     src 目录下 utils 目录下,新建 request.ts,因为使用的是TS,需要提前定义数据格式:定义请求数据返回的格式,需要提前确认好定义 axios 基础配置信息请求拦截器:所有请求最先到达的地方,我们可以在此自定义请求头信息(比如:token、多语言等等)响应拦截器:返回数据最先到达的地方,我们可以在此处理异常信息(比如:code为401重定向至登录、code为500提示错误信息)
    import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
    import { ElMessage, ElLoading, ElMessageBox } from "element-plus";
     
    // response interface { code, msg, success }
    // 不含 data
    interface Result {
        code: number,
        success: boolean,
        msg: string
    }
     
    // request interface,包含 data
    interface ResultData extends Result {
        data?: T
    }
     
    enum RequestEnums {
        TIMEOUT = 10000, // 请求超时 request timeout
        FAIL = 500, // 服务器异常 server error
        LOGINTIMEOUT = 401, // 登录超时 login timeout
        SUCCESS = 200, // 请求成功 request successfully
    }
     
    // axios 基础配置
    const config = {
        // 默认地址,可以使用 process Node内置的,项目根目录下新建 .env.development
        baseURL: process.env.VUE_APP_BASE_API as string,
        timeout: RequestEnums.TIMEOUT as number, // 请求超时时间
        withCredentials: true, // 跨越的时候允许携带凭证
    }
     
    class Request {
        service: AxiosInstance;
     
        constructor(config: AxiosRequestConfig) {
            // 实例化 serice
            this.service = axios.create(config);
     
            /**
             * 请求拦截器
             * request -> { 请求拦截器 } -> server
             */
            this.service.interceptors.request.use(
                (config: AxiosRequestConfig) => {
                    const token = localStorage.getItem('token') ?? '';
                    return {
                        ...config,
                        headers: {
                            'customToken': "customBearer " + token
                        }
                    }
                },
                (error: AxiosError) => {
                    // 请求报错
                    Promise.reject(error)
                }
            );
     
            /**
             * 响应拦截器
             * response -> { 响应拦截器 } -> client
             */
            this.service.interceptors.response.use(
                (response: AxiosResponse) => {
                    const { data, config } = response;
                    if (data.code === RequestEnums.LOGINTIMEOUT) {
                        // 表示登录过期,需要重定向至登录页面
                        ElMessageBox.alert("Session expired", "System info", {
                            confirmButtonText: 'Relogin',
                            type: 'warning'
                        }).then(() => {
                            // 或者调用 logout 方法去处理
                            localStorage.setItem('token', '');
                            location.href = '/'
                        })
                    }
                    if (data.code && data.code !== RequestEnums.SUCCESS) {
                        ElMessage.error(data);
                        return Promise.reject(data);
                    }
                    return data
                },
                (error: AxiosError) => {
                    const { response } = error;
                    if (response) {
                        this.handleCode(response.status);
                    }
                    if (!window.navigator.onLine) {
                        ElMessage.error("网络连接失败,请检查网络");
                        // 可以重定向至404页面
                    }
                }
     
            )
        }
     
        public handleCode = (code: number): void => {
            switch (code) {
                case 401:
                    ElMessage.error("登陆失败,请重新登录");
                    break;
                case 500:
                    ElMessage.error("请求异常,请联系管理员");
                    break;
                default:
                    ElMessage.error('请求失败');
                    break;
            }
        }
     
        // 通用方法封装
        get(url: string, params?: object): Promise> {
            return this.service.get(url, { params });
        }
     
        post(url: string, params?: object): Promise> {
            return this.service.post(url, params);
        }
        put(url: string, params?: object): Promise> {
            return this.service.put(url, params);
        }
        delete(url: string, params?: object): Promise> {
            return this.service.delete(url, { params });
        }
    }
     
    export default new Request(config)

    3. 实际使用

    src 目录下新增 api/index.ts

    • 定义请求的参数类型

    • 定义响应想具体参数类型

    这里我们使用到ts 中的 namespace ,实际开发中我们很多 api 可能会出现相同名字不同含义,所以我们使用 namespace 进行定义

    import request from "@/utils/request";
     
    namespace User {
        // login
        export interface LoginForm {
            userName: string,
            password: string
        }
    }
     
     
    export namespace System {
     
     
        export interface Info {
            path: string,
            routeName: string
        }
     
     
        export interface ResponseItem {
            code: number,
            items: Array,
            success: boolean
        }
     
        export interface Sidebar {
            id: number,
            hashId: string | number,
            title: string,
            routeName: string,
            children: Array,
        }
     
        export interface SidebarItem {
            id: number,
            parentId: number,
            hashId: string | number,
            title: string,
        }
    }
     
    export const info = (params: System.Info) => {
        // response 
        if (!params || !params.path) throw new Error('Params and params in path can not empty!')
        // 这里因为是全局的一个info,根据路由地址去请求侧边栏,所需不用把地址写死
        return request.post(params.path, { routeName: params.routeName })
    }

    Vue 文件中调用

    Videoleap
    Videoleap

    Videoleap是一个一体化的视频编辑平台

    下载

    二、 mock.js 的依赖安装与处理  

    1. 安装依赖

    # 安装
    npm install mockjs --save

      在 ts 中使用时,我们需要现在 shims-vue.d.ts 文件中去抛出模块,不然会出现引入报错的问题

    /* eslint-disable */
    declare module '*.vue' {
      import type { DefineComponent } from 'vue'
      const component: DefineComponent<{}, {}, any>
      export default component
    }
     
    declare module 'mockjs';

    2. 新建 mock 所需的文件

    vue3和ts封装axios及使用mock.js的方法是什么

     index.ts(属于mockjs全局配置文件),mockjs/javaScript/index.ts(具体的数据文件),这两个需要关注,别的不用关注

    1. 新建 mockjs/javaScript/index.ts(具体的数据文件) 

    因为我这里的数据主要是 侧边栏的数据,都是固定好的,所以并没有用到 mockjs 的规则生成数据

    import { GlobalSidebar, Sidebar } from "../../sidebar";
     
    namespace InfoSidebar {
        export type InfoSidebarParams = {
            body: string,
            type: string,
            url: string
        }
    }
     
    const dataSource: Array = [
        {
            mainTitle: 'JavaScript基础问题梳理',
            mainSidebar: [
                {
                    id: 0,
                    hashId: 'This',
                    title: 'this指向',
                    routeName: 'JsBasic',
                    children: [
                        {
                            id: 1,
                            parentId: 0,
                            hashId: 'GlobalFunction',
                            title: '全局函数'
                        },
                        {
                            id: 2,
                            parentId: 0,
                            hashId: 'ObjectMethod',
                            title: '对象方法'
                        },
                        {
                            id: 3,
                            parentId: 0,
                            hashId: 'Constructor',
                            title: '构造函数'
                        },
                        {
                            id: 4,
                            parentId: 0,
                            hashId: 'SetTimeout',
                            title: '定时器、回调函数'
                        },
                        {
                            id: 5,
                            parentId: 0,
                            hashId: 'EventFunction',
                            title: '事件函数'
                        },
                        {
                            id: 6,
                            parentId: 0,
                            hashId: 'ArrowFunction',
                            title: '箭头函数'
                        },
                        {
                            id: 7,
                            parentId: 0,
                            hashId: 'CallApplyBind',
                            title: 'call、apply、bind'
                        },
                    ]
                },
                {
                    id: 2,
                    hashId: 'DeepClone',
                    title: '深拷贝和浅拷贝',
                    routeName: 'JsBasic',
                    children: []
                }
            ]
        },
    ];
     
    export default {
        name: 'jsBasicInfo',
        jsBasicInfo(params: InfoSidebar.InfoSidebarParams) {
            const param = JSON.parse(params.body)
            if (!param) throw new Error("Params can not empty!");
            const data = dataSource.find((t: GlobalSidebar) => {
                return t.mainSidebar.filter((x: Sidebar) => {
                    return x.routeName === param.routeName
                })
            })
            return {
                data,
                success: true,
                code: 200
            }
        }
    }

    Sidebar.ts

    /**
     * @param { number } id Unique value
     * @param { string } hashId href Unique value
     * @param { string } title show current title
     * @param { string } routeName page find data
     */
     
    interface GlobalSidebar {
        mainTitle: string,
        mainSidebar: Array
    }
     
    interface Sidebar {
        id: number,
        hashId: string | number,
        title: string,
        routeName: string,
        children: Array,
    }
     
    interface SidebarItem {
        id: number,
        parentId: number,
        hashId: string | number,
        title: string,
    }
     
    export {
        GlobalSidebar,
        Sidebar,
        SidebarItem
    }

    2. 新建 mockjs/index.ts 

    import Mock from "mockjs";
    import jsBasicInfo from "./tpl/javaScript/index";
    const requestMethod = 'post';
    const BASE_URL = process.env.VUE_APP_BASE_API;
    const mocks = [jsBasicInfo];
     
    for (let i of mocks) {
        Mock.mock(BASE_URL + '/' + i.name, requestMethod, i.jsBasicInfo);
    }
     
    export default Mock

    3. main.ts 引入

    import { createApp } from 'vue'
    import App from './App.vue'
     
    if(process.env.NODE_ENV == 'development'){
        require('./mockjs/index')
    }
     
    const app = createApp(App);
    app.mount('#app');

    三、结合使用

    实际上就是刚刚调用axios 的那一段代码

    相关专题

    更多
    js获取数组长度的方法
    js获取数组长度的方法

    在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

    542

    2023.06.20

    js刷新当前页面
    js刷新当前页面

    js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

    372

    2023.07.04

    js四舍五入
    js四舍五入

    js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

    727

    2023.07.04

    js删除节点的方法
    js删除节点的方法

    js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

    470

    2023.09.01

    JavaScript转义字符
    JavaScript转义字符

    JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

    392

    2023.09.04

    js生成随机数的方法
    js生成随机数的方法

    js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

    990

    2023.09.04

    如何启用JavaScript
    如何启用JavaScript

    JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

    654

    2023.09.12

    Js中Symbol类详解
    Js中Symbol类详解

    javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

    544

    2023.09.20

    php源码安装教程大全
    php源码安装教程大全

    本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

    7

    2025.12.31

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Vue3.x 工具篇--十天技能课堂
    Vue3.x 工具篇--十天技能课堂

    共26课时 | 1.4万人学习

    Vue3.x 核心篇--十天技能课堂
    Vue3.x 核心篇--十天技能课堂

    共30课时 | 1.4万人学习

    Vue3.x新特性篇--十天基础课堂
    Vue3.x新特性篇--十天基础课堂

    共20课时 | 1.1万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号