Axios相關
1.在Axios二次封裝時,具體封裝了哪些內容,如何處理請求攔截和響應攔截?
axios二次封裝的目的:為了統一處理請求和響應攔截器、錯誤處理、請求超時、請求頭配置等,提高代碼可維護性和復用性。
- 首先創建axios實例,配置基礎的URL和請求超時時間。
- 請求攔截器:用于在發送請求之前進行一些預處理,像,檢查本地存儲中是否存在token,當前請求的URL是否在白名單中,如果token存在且URL不在白名單中,會在請求頭中添加token.
- 響應攔截器:用于在接收到響應之后進行一些處理。根據后臺返回的code數據,使用ElMessage顯示信息,如果token錯誤或過期,會清除本地存儲中的相關數據,并將用戶重定向到登錄頁面。
- 導出Axios實例:在其他部分使用,可以通過這個實例發出HTTP請求,不需要每次都重新配置Axios 。如在API請求封裝文件導入了axios的二次封裝,getCode函數內部調用了request.post方法發出請求。request.post就是axios文件中配置好的實例post方法。
2.如何處理全局的錯誤碼返回的,比如token失效、權限不足等情況?
在響應式攔截器中,根據后端返回的code進行不同處理
3.Aixos封裝是否支持取消請求,如果一個用戶在短時間內連續點擊多個請求?
使用axios.CancelToken來取消重復請求,防止用戶多次點擊按鈕導致接口請求重復。
Vuex相關
4.如何實現Vuex數據持久化的?
Vuex 默認存儲在內存中,刷新頁面后會丟失數據。我使用
vuex-persistedstate
進行持久化存儲,存入localStorage
或sessionStorage
。刷新后將動態路由添加到main.js中。vuex持久化是通過localStorage實現的,具體來說,是在狀態初始化時從localStorage中讀取數據,并在狀態變化時將新的狀態保存到localStorage中,這種做法可以確保即使在頁面刷新后,vuex的狀態依然保持不變。?
在mutation中,通過設置動態菜單的函數,動態導入vue組件并設置路由組件,實現了動態路由的添加,在mutation中監聽狀態變化,然后將新的狀態保存在LocalStorage中。
5.在Vuex中如何涉及store結構
使用 模塊化 (modules
) 的方式,將 Vuex 按功能拆分。
6.Vuex和Pinia有什么區別?
vuex通過一個store對象來管理所有狀態,使狀態管理變得集中和統一
pinia:分離模式,每個組件都可以擁有自己的store實例,提高性能。沒有modules配置,體積也更小。
路由相關
1.前置路由守衛的作用?router.beforeEach()
用戶導航到某個路由之前進行身份驗證或其他邏輯判斷.
重定向:用戶嘗試訪問非登錄頁面且token不存在,則重定向到登錄頁面,如果用戶已經登錄(token存在)嘗試訪問登錄頁面時,則重定向到首頁。
2.Aiosx Token校驗的作用和路由守衛結合的原因:
axios設置請求攔截器來添加token,在響應式攔截器中處理token過期的情況,主要時為了確保每個API請求都帶有正確的認證信息。
將前置路由守衛和Axios Token結合使用的原因:
- 細粒度控制:路由守衛提供了更細粒度的訪問控制,可以在用戶嘗試訪問某個頁面之前就阻止未授權的訪問,而不必等到 API 請求失敗。
- 用戶體驗:通過路由守衛,可以防止用戶在嘗試訪問受保護的頁面時看到加載中的狀態或錯誤信息,直接重定向到登錄頁面可以提高用戶體驗。
3.路由重定向的實現 redirect
用于在用戶登錄后根據存儲在本地的路由信息決定重定向到哪個頁面。如果本地沒有存儲路由的信息,則重定向到登錄頁面。
組件庫的使用:
1.Element Plus和Vant的主要區別是什么?在什么場景下使用它們?
Element Plus:使用于PC端,基于vue3的UI組件庫。依賴
Vue 3
生態,如setup()
和Composition API
。Vant:適用于移動端。內置
Flex 布局
,支持Vue 2
和Vue 3。
2.如何在同一個項目中同時兼容PC端和移動端的UI組件?
方法 1:使用不同的組件庫(Element Plus + Vant)
方法 2:使用響應式 CSS + flex/grid
.container {display: flex;flex-direction: column;
}@media screen and (min-width: 768px) {.container {flex-direction: row;}
}
方法 3:使用 rem
+ vw
進行適配
html {font-size: calc(100vw / 10);
}
頁面根據屏幕大小自動縮小,無需手動調整組件。
二維碼支付
1.如何使用 Qrcode 生成二維碼?如何優化二維碼的清晰度?
我使用 qrcode
庫來生成二維碼
優化清晰度
errorCorrectionLevel: "H"
(最高容錯等級,防止二維碼損壞后無法識別)scale: 8
(增大像素密度,避免模糊)margin: 1
(減少周圍白邊)
2.在支付過程中,你是如何保證數據安全性的?
- HTTPS 加密 → 確保支付信息不被劫持。
- Token 驗證 → 在支付請求中附帶
JWT
,后端驗證后才能處理支付請求。 - 簽名機制 → 前端請求支付接口時,后端返回
簽名字符串
,防止數據篡改。 - 定期刷新 Token → 避免 Token 被濫用。
Vite相關
1.為什么選擇 Vite 作為構建工具?相較于 Webpack,它的優勢是什么?
webpack會對所有模塊進行打包操作,配置復雜,需要編寫大量配置文件,功能豐富,適合大型復雜的項目。
vite沒有打包的步驟,而是直接啟動一個開發服務器,按需加載模塊,響應速度提高。大部分無需自己寫配置文件。輕量和速度優勢,適合中小型項目。
2.vite的快速冷啟動和即時熱更新
快速冷啟動:指在vite啟動開發服務器時,能夠迅速完成初始化并啟動服務,使得開發者可以立即開始開發工作。
即時熱更新:當代碼發生變化時,vite能夠實時地將這些變化推送到瀏覽器中,無需手動刷新頁面,允許開發者在編寫代碼時能夠立即看到效果從而加快開發速度和迭代效率。
3.webSocket
WebSocket是HTML5引入的一項技術,用于在Web應用程序中實現實時雙向通信。WebSocket允許服務器主動向客戶端推送數據,不需要客戶端發起請求。
特點:
- 實時雙向通信:一旦建立了WebSocket連接,客戶端和服務器可以通過該連接進行雙向的實時數據傳輸。
- 持久化連接:WebSocket連接保持打開狀態,允許客戶端和服務器之間進行持續通信,無需頻繁建立連接。
- 高效性:通過減少HTTP請求的次數和降低網絡延遲,WebSocket提供了更高效和實時的通信方式。
vite在開發服務器和瀏覽器之間建立了一個持久的雙向通信通道(websocket),通過者通道,開發服務器可以實時地將代碼變化推送給瀏覽器。
異步處理
1.在 API 調用中,你是如何處理請求失敗或超時的?
在axios實例中設置了timeout屬性為10000毫秒(10s),意味著如果請求在10s內沒有完成,會自動觸發超時錯誤。超時錯誤會進入響應攔截中。
- 設置
timeout
,超時自動取消 try-catch
處理異常,顯示友好錯誤提示
2.async/await
和 .then().catch()
方式的區別是什么?
async/await → 語法簡潔,可讀性高
then().catch() → 適用于 Promise 鏈式調用
3.如果多個 API 需要并行調用,你會如何優化?
使用 Promise.all()
并行執行多個 API:提高性能,減少等待時間。
const [user, orders] = await Promise.all([axios.get("/api/user"),axios.get("/api/orders"),
]);
性能優化
1.KeepAlive緩存?
<keep-alive>是一個內置組件,用于緩存組件實例,避免在切換時重復渲染和銷毀,對于性能優化特別有用,尤其在用戶頻繁切換頁面或者組件的情況下,可以減少不必要的DOM操作和計算,提高用戶體驗。
用法:<keep-alive>包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們,當組件再次變得活躍狀態時,會復用這些緩存的實例,而不是重新創建。
在Vue Router中,通過路由元信息(meta)來控制哪些路由下的組件需要<keep-alive>緩存
const router = new VueRouter({routes: [{path: '/foo',component: Foo,meta: { keepAlive: true } // 標記該路由下的組件需要被緩存},{path: '/bar',component: Bar}] });
在App.vue或者布局組件中使用<keep-alive>并結合路由的meta信息來決定是否緩存。
<template><div id="app"><router-view v-if="$route.meta.keepAlive" key="$route.path"></router-view><keep-alive><router-view v-if="!$route.meta.keepAlive" key="$route.path"></router-view></keep-alive></div> </template>
?生命周期鉤子:
別<keep-alive>包裹的組件會有特殊的生命周期鉤子:
activated:當組件被激活(從緩存中取出并顯示到頁面)時調用。
deactivated:當組件被停用(從界面移除并緩存起來)時調用。
這意味著原本的mounted和destroyed鉤子在被緩存的組件不會被調用,因為組件實例沒有真正地被創建或銷毀。
2.懶加載非核心模塊時,具體是如何實現的,有沒有遇到預加載或依賴加載的問題?
定義:路由懶加載也叫延遲加載,在需要的時候進行加載,隨用隨載。把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應的組件,更加高效。
為什么需要懶加載:如果沒有很多頁面都放在同一個js文件中,運用webpack打包后文件將異常大,進入頁面時,需要加載的內容多,時間長,會出現長時間的白屏。運用懶加載可以將頁面進行劃分,需要的時候加載頁面,可以有效的分擔首頁所承擔的加載壓力,減少首頁加載用時。
懶加載做了什么事:將路由對應的組件打包成一個個的js代碼塊,只有這個路由被訪問時才加載對應組件,否則不加載。
?非懶加載示例:
// 非懶加載
import Home from '@/components/Home'const routes = [{path: '/home',name: 'home',component: Home}
]
?三種方式實現懶加載
vue異步組件
vue-router配置路由,使用vue的異步組件技術,實現按需加載,在這種情況下每一個組件就會生成一個js文件,不能分類指定chunkName
// vue異步組件
{path: '/home',name: 'home',component: resolve => require(['放入需要加載的路由地址'], resolve)
}
ES6推薦方式import()
直接將組件引入的方式,import是Es6的一個語法標準
使用魔法注釋/* webpackChunkName: 'ImportFuncDemo' */ 打包到一個js文件里。
import Vue from 'vue';
import Router from 'vue-router';
// 官網可知:下面沒有指定webpackChunkName,每個組件打包成一個js文件。
const Foo = () => import('../components/Foo')
const Aoo = () => import('../components/Aoo')
// 下面2行代碼,指定了相同的webpackChunkName,會合并打包成一個js文件。
// const Foo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/Foo')
// const Aoo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/Aoo')
export default new Router({routes: [{path: '/Foo',name: 'Foo',component: Foo},{path: '/Aoo',name: 'Aoo',component: Aoo}]
})
?webpack提供的require.ensure()實現懶加載
可以實現按需加載,多個路由指定相同的chunkName,會合并打包成一個js文件。
chunkName用于命名生成的懶加載文件
import Vue from 'vue';
import Router from 'vue-router';
const HelloWorld=resolve=>{
//@指向src目錄 這個路徑是需要懶加載的組件路徑require.ensure(['@/components/HelloWorld'],()=>{resolve(require('@/components/HelloWorld'))})}
Vue.use('Router')
export default new Router({routes:[{{path:'./',name:'HelloWorld',component:HelloWorld}}]
})