Vue3中路由跳轉(zhuǎn)優(yōu)化技巧分享
為什么需要這個優(yōu)化
想象一下你去快餐店點餐:
- 原始體驗:你點完漢堡后,服務(wù)員直接消失,你傻站著等,突然就把漢堡塞你手里(類似Vue默認路由跳轉(zhuǎn))
- 優(yōu)化后體驗:點完漢堡,服務(wù)員說"請稍等",屏幕上顯示制作進度條,漢堡做好后優(yōu)雅地遞給你
實現(xiàn)原理圖解

手把手實現(xiàn)絲滑過渡效果
項目初始化準備
確保你有一個Vue3項目
npm init vue@latest my-project cd my-project npm install
安裝必要依賴
npm install nprogress # 如果要用進度條方案
創(chuàng)建全局加載組件(全屏方案)
在src/components下新建GlobalLoading.vue
<template>
<div v-if="isLoading" class="global-loading">
<div class="loading-overlay"></div>
<div class="loading-spinner">
<div class="spinner"></div>
<div class="loading-text">加載中...</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const isLoading = ref(false);
const show = () => { isLoading.value = true };
const hide = () => { isLoading.value = false };
defineExpose({ show, hide });
</script>
<style scoped>
.global-loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
}
.loading-overlay {
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px);
}
.loading-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
color: white;
font-size: 16px;
}
</style>
修改App.vue掛載組件
修改src/App.vue
<template>
<RouterView />
<GlobalLoading ref="globalLoading" />
</template>
<script setup>
import { ref, onMounted } from 'vue';
import GlobalLoading from '@/components/GlobalLoading.vue';
const globalLoading = ref(null);
// 全局掛載方法
onMounted(() => {
window.__globalLoading = globalLoading.value;
});
</script>
配置路由守衛(wèi)
修改src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// 懶加載示例
component: () => import('../views/AboutView.vue')
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
// 添加路由守衛(wèi)
router.beforeEach(async (to, from, next) => {
// 顯示加載動畫
if (window.__globalLoading) {
window.__globalLoading.show();
}
try {
// 處理懶加載路由
const matchedComponents = to.matched.flatMap(record =>
Object.values(record.components)
);
await Promise.all(
matchedComponents.map(component => {
if (typeof component === 'function') {
return component();
}
return Promise.resolve();
})
);
next();
} catch (err) {
console.error('路由加載失敗:', err);
next(false);
} finally {
// 確保加載動畫至少顯示300ms
setTimeout(() => {
if (window.__globalLoading) {
window.__globalLoading.hide();
}
}, 300);
}
});
export default router;
進度條方案實現(xiàn)(可選)
在src/router/index.js中添加
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
// 配置NProgress
NProgress.configure({
showSpinner: false,
minimum: 0.3,
speed: 500
});
// 修改路由守衛(wèi)
router.beforeEach((to, from, next) => {
NProgress.start();
next();
});
router.afterEach(() => {
NProgress.done();
});
測試你的實現(xiàn)
創(chuàng)建測試視圖
# 創(chuàng)建兩個測試頁面 touch src/views/HomeView.vue touch src/views/AboutView.vue
在AboutView.vue中添加延遲
<script setup> // 模擬網(wǎng)絡(luò)延遲 await new Promise(resolve => setTimeout(resolve, 1000)); </script>
添加導(dǎo)航鏈接
在任意頁面添加:
<router-link to="/">Home</router-link> | <router-link to="/about">About</router-link>
效果驗證
當你點擊About鏈接時,應(yīng)該能看到:
- 頁面變灰并顯示加載動畫
- 1秒后(模擬的延遲)跳轉(zhuǎn)到About頁面
- 加載動畫消失
高級定制技巧
按路由類型顯示不同加載效果
// 在路由配置中添加meta
{
path: '/dashboard',
component: () => import('@/views/Dashboard.vue'),
meta: { loadingType: 'progress' } // 或'fullscreen'
}
// 修改路由守衛(wèi)
router.beforeEach((to) => {
if (to.meta.loadingType === 'progress') {
NProgress.start();
} else {
window.__globalLoading?.show();
}
});
添加骨架屏
<!-- 在懶加載組件中 -->
<template>
<div v-if="!isLoaded">
<!-- 骨架屏內(nèi)容 -->
<div class="skeleton-header"></div>
<div class="skeleton-content"></div>
</div>
<div v-else>
<!-- 實際內(nèi)容 -->
</div>
</template>
常見問題解決
加載動畫不顯示?
- 檢查
window.__globalLoading是否正確掛載 - 確認路由組件是否真的異步加載(使用
() => import()語法)
動畫閃爍太快?
// 增加最小顯示時間
let timer = setTimeout(() => {
window.__globalLoading?.hide();
}, 500); // 至少顯示500毫秒
// 在組件加載完成后清除計時器
await componentLoaded;
clearTimeout(timer);
TypeScript支持
// 在src/shims-global.d.ts中添加
declare global {
interface Window {
__globalLoading: {
show: () => void;
hide: () => void;
};
}
}
現(xiàn)在你的Vue3應(yīng)用應(yīng)該擁有了專業(yè)的路由過渡效果!可以通過調(diào)整動畫樣式、持續(xù)時間和觸發(fā)條件來進一步優(yōu)化用戶體驗。
常見問題解答
Q:為什么我的加載動畫一閃而過?
A:就像你眨眼太快看不到東西一樣,可能是因為:
- 組件已經(jīng)預(yù)加載了(檢查路由配置)
- 網(wǎng)絡(luò)太快(可以加個setTimeout最小顯示時間)
Q:如何讓不同路由顯示不同加載動畫?
A:可以這樣定制:
router.beforeEach((to) => {
if (to.meta.loadingType === 'fullscreen') {
showFullLoading()
} else {
showProgressBar()
}
})
Q:加載時用戶還能操作頁面嗎?
A:默認不能,就像電梯運行時按鈕會暫時失效。如果需要允許操作:
.loading-overlay {
pointer-events: none; /* 添加這行 */
}
性能優(yōu)化建議
預(yù)加載策略:像提前預(yù)熱烤箱
// 在空閑時預(yù)加載可能訪問的路由
import('@/views/About.vue')
骨架屏:像先把餐桌擺好再上菜
<!-- 在組件中添加骨架屏 --> <template v-if="loading"> <SkeletonLoader /> </template>
智能延遲:如果加載<300ms就不顯示動畫
let timer = setTimeout(showLoading, 300) // 如果提前完成就取消計時器
到此這篇關(guān)于Vue3中路由跳轉(zhuǎn)優(yōu)化技巧分享的文章就介紹到這了,更多相關(guān)Vue3路由跳轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 使用async寫數(shù)字動態(tài)加載效果案例
這篇文章主要介紹了vue 使用async寫數(shù)字動態(tài)加載效果案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vuex?mutation?action同級調(diào)用方式
這篇文章主要介紹了vuex?mutation?action同級調(diào)用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
vue踩坑記-在項目中安裝依賴模塊npm install報錯
這篇文章主要介紹了vue踩坑記-在項目中安裝依賴模塊npm install報錯,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04

