中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2023-02-20 10:18:29 來源:億速云 閱讀:160 作者:iii 欄目:開發技術

這篇文章主要講解了“vue3和ts封裝axios及使用mock.js的方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“vue3和ts封裝axios及使用mock.js的方法是什么”吧!

    前言

    我們要注意區分 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<T = any> 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<T>(url: string, params?: object): Promise<ResultData<T>> {
            return this.service.get(url, { params });
        }
     
        post<T>(url: string, params?: object): Promise<ResultData<T>> {
            return this.service.post(url, params);
        }
        put<T>(url: string, params?: object): Promise<ResultData<T>> {
            return this.service.put(url, params);
        }
        delete<T>(url: string, params?: object): Promise<ResultData<T>> {
            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<Sidebar>,
            success: boolean
        }
     
        export interface Sidebar {
            id: number,
            hashId: string | number,
            title: string,
            routeName: string,
            children: Array<SidebarItem>,
        }
     
        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<System.Sidebar>(params.path, { routeName: params.routeName })
    }

    Vue 文件中調用

    <script lang="ts" setup name="Sidebar">
    import { ref, reactive, onBeforeMount } from "vue"
    import { info } from "@/api"
    import { useRoute } from "vue-router"
    const route = useRoute();
     
    let loading = ref<boolean>(false);
    let sidebar = ref<any>({});
     
    const _fetch = async (): Promise<void> => {
        const routeName = route.name as string;
        const path = '/' + routeName.replace(routeName[0], routeName[0].toLocaleLowerCase()) + 'Info'
        try {
            loading.value = true;
            const res = await info({ path, routeName });
            if (!res || !res.data) return;
            sidebar.value = res.data;
        } finally {
            loading.value = false
        }
    }
     
    onBeforeMount(() => {
        _fetch();
    })
     
    </script>

    二、 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<GlobalSidebar> = [
        {
            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<Sidebar>
    }
     
    interface Sidebar {
        id: number,
        hashId: string | number,
        title: string,
        routeName: string,
        children: Array<SidebarItem>,
    }
     
    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 的那一段代碼

    <script lang="ts" setup name="Sidebar">
    import { ref, reactive, onBeforeMount } from "vue"
    import { info } from "@/api"
    import { useRoute } from "vue-router"
    const route = useRoute();
     
    let loading = ref<boolean>(false);
    let sidebar = ref<any>({});
     
    const _fetch = async (): Promise<void> => {
        const routeName = route.name as string;
        const path = '/' + routeName.replace(routeName[0], routeName[0].toLocaleLowerCase()) + 'Info'
        try {
            loading.value = true;
            const res = await info({ path, routeName });
            if (!res || !res.data) return;
            sidebar.value = res.data;
        } finally {
            loading.value = false
        }
    }
     
    onBeforeMount(() => {
        _fetch();
    })
     
    </script>

    感謝各位的閱讀,以上就是“vue3和ts封裝axios及使用mock.js的方法是什么”的內容了,經過本文的學習后,相信大家對vue3和ts封裝axios及使用mock.js的方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    银川市| 新昌县| 深州市| 大田县| 平邑县| 宜兴市| 科技| 延津县| 霍林郭勒市| 二连浩特市| 兰坪| 青阳县| 尼木县| 额尔古纳市| 凤翔县| 南平市| 辰溪县| 连山| 新巴尔虎左旗| 青铜峡市| 沽源县| 宜良县| 平武县| 雷山县| 宁南县| 大渡口区| 马公市| 西乡县| 大足县| 巴彦县| 科尔| 四川省| 五台县| 合作市| 河池市| 福清市| 文山县| 沛县| 当阳市| 阿鲁科尔沁旗| 大荔县|