您好,登錄后才能下訂單哦!
這篇文章主要講解了“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
使用異步網絡請求肯定離不開loading、message 等提示,今天我們配合 elementPlus 一起使用;
// 安裝axios npm install axios --save // 安裝 elementPlus npm install element-plus --save
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)
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>
# 安裝 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';
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的方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。