Vue-Router路由守衛(wèi)詳?shù)募?xì)用法教程
引言
在Vue.js應(yīng)用中,Vue-Router是一個(gè)非常重要的插件,它允許我們實(shí)現(xiàn)頁(yè)面間的導(dǎo)航。然而,僅僅實(shí)現(xiàn)導(dǎo)航是不夠的,我們還需要在導(dǎo)航的不同階段進(jìn)行各種操作,如用戶(hù)認(rèn)證、權(quán)限管理、數(shù)據(jù)預(yù)加載等。這時(shí),路由守衛(wèi)就派上了用場(chǎng)。本文將結(jié)合實(shí)際案例,詳細(xì)介紹Vue-Router路由守衛(wèi)的用法。
一、路由守衛(wèi)的基本概念
路由守衛(wèi)是Vue-Router提供的一種機(jī)制,用于在路由跳轉(zhuǎn)前或跳轉(zhuǎn)后執(zhí)行一些操作。它類(lèi)似于Vue組件中的生命周期鉤子函數(shù),但它是針對(duì)路由的。通過(guò)路由守衛(wèi),我們可以在用戶(hù)訪問(wèn)特定路由前或離開(kāi) 特定路由后執(zhí)行一些邏輯,從而控制用戶(hù)訪問(wèn)權(quán)限、加載數(shù)據(jù)或取消導(dǎo)航等操作。
Vue-Router中的路由守衛(wèi)主要分為三類(lèi):全局守衛(wèi)、路由獨(dú)享守衛(wèi)和組件內(nèi)守衛(wèi)。
- 全局守衛(wèi):在整個(gè)應(yīng)用的任何路由跳轉(zhuǎn)前或跳轉(zhuǎn)后執(zhí)行。全局守衛(wèi)適用于應(yīng)用級(jí)別的邏輯,如用戶(hù)登錄狀態(tài)檢查。
- 路由獨(dú)享守衛(wèi):在特定路由跳轉(zhuǎn)前或跳轉(zhuǎn)后執(zhí)行。路由獨(dú)享守衛(wèi)適用于特定路由的邏輯,如管理員權(quán)限檢查。
- 組件內(nèi)守衛(wèi):定義在組件內(nèi)部的守衛(wèi),它分為beforeRouteEnter、beforeRouteUpdate和beforeRouteLeave。組件內(nèi)守衛(wèi)適合與組件自身相關(guān)的邏輯,如數(shù)據(jù)預(yù)加載和頁(yè)面離開(kāi)確認(rèn)。
二、全局守衛(wèi)
全局守衛(wèi)是在Vue Router實(shí)例上注冊(cè)的,可以對(duì)所有路由變化進(jìn)行監(jiān)聽(tīng)。全局守衛(wèi)包括全局前置守衛(wèi)(beforeEach)、全局解析守衛(wèi)(beforeResolve)和全局后置守衛(wèi)(afterEach)。
- 全局前置守衛(wèi)(beforeEach)
全局前置守衛(wèi)在每次導(dǎo)航之前調(diào)用,常用于檢查用戶(hù)是否登錄以及用戶(hù)權(quán)限驗(yàn)證等。
示例代碼:
import Vue from 'vue'; import Router from 'vue-router'; import Home from '@/components/Home'; import About from '@/components/About'; import Login from '@/components/Login'; Vue.use(Router); const router = new Router({ routes: [ { path: '/', component: Home }, { path: '/about', component: About, meta: { requiresAuth: true } }, { path: '/login', component: Login } ] }); // 假設(shè)我們有一個(gè)檢查用戶(hù)是否登錄的函數(shù) function isUserLoggedIn() { // 這里可以是一個(gè)實(shí)際的登錄檢查邏輯,比如查詢(xún)cookie或Vuex狀態(tài) return false; // 這里我們假設(shè)用戶(hù)未登錄 } // 全局前置守衛(wèi) router.beforeEach((to, from, next) => { // 檢查目標(biāo)路由是否需要認(rèn)證 if (to.meta.requiresAuth && !isUserLoggedIn()) { // 如果需要認(rèn)證且用戶(hù)未登錄,則跳轉(zhuǎn)到登錄頁(yè) next('/login'); } else { // 否則允許訪問(wèn) next(); } }); export default router;
在上面的示例中,我們定義了一個(gè)全局前置守衛(wèi),它會(huì)在每次路由跳轉(zhuǎn)前檢查目標(biāo)路由是否需要認(rèn)證(通過(guò)meta屬性中的requiresAuth標(biāo)識(shí))。如果需要認(rèn)證且用戶(hù)未登錄,則重定向到登錄頁(yè)。
- 全局解析守衛(wèi)(beforeResolve)
全局解析守衛(wèi)在導(dǎo)航被確認(rèn)前調(diào)用,常用于異步獲取數(shù)據(jù)后再渲染組件的場(chǎng)景。這個(gè)守衛(wèi)與全局前置守衛(wèi)類(lèi)似,但它在導(dǎo)航被確認(rèn)之前被調(diào)用,這意味著它可以在導(dǎo)航被阻止之前解析數(shù)據(jù)。
示例代碼:
router.beforeResolve((to, from, next) => { // 在這里進(jìn)行異步數(shù)據(jù)獲取操作 // 比如通過(guò)API請(qǐng)求獲取數(shù)據(jù) console.log('導(dǎo)航即將被確認(rèn),可以進(jìn)行數(shù)據(jù)獲取操作'); next(); });
在上面的示例中,我們?cè)谌纸馕鍪匦l(wèi)中進(jìn)行了數(shù)據(jù)獲取操作。注意,這個(gè)守衛(wèi)不會(huì)中斷導(dǎo)航過(guò)程,它只是用于在導(dǎo)航確認(rèn)之前進(jìn)行數(shù)據(jù)獲取。
- 全局后置守衛(wèi)(afterEach)
全局后置守衛(wèi)在每次導(dǎo)航之后調(diào)用,常用于統(tǒng)計(jì)頁(yè)面PV、修改頁(yè)面title等操作。這個(gè)守衛(wèi)不接受next函數(shù),也不可以中斷導(dǎo)航。
示例代碼:
router.afterEach((to, from) => { // 在這里進(jìn)行頁(yè)面title設(shè)置等操作 document.title = to.meta.title || '默認(rèn)標(biāo)題'; console.log('導(dǎo)航已完成'); });
在上面的示例中,我們?cè)谌趾笾檬匦l(wèi)中設(shè)置了頁(yè)面title,并打印了導(dǎo)航完成的消息。
三、路由獨(dú)享守衛(wèi)
路由獨(dú)享守衛(wèi)是在路由配置中直接定義的守衛(wèi),它只應(yīng)用于單個(gè)路由或一組路由。這種守衛(wèi)允許我們針對(duì)特定的路由實(shí)施一些邏輯,如驗(yàn)證用戶(hù)是否有權(quán)限訪問(wèn)某個(gè)頁(yè)面。
示例代碼:
const routes = [ { path: '/admin', component: Admin, meta: { requiresAuth: true, requiresAdmin: true }, beforeEnter: (to, from, next) => { // 假設(shè)我們有一個(gè)檢查用戶(hù)是否登錄和是否具備管理員權(quán)限的函數(shù) function isUserLoggedIn() { return false; } // 用戶(hù)未登錄 function isUserAdmin() { return true; } // 用戶(hù)是管理員(這里只是模擬) // 檢查用戶(hù)是否登錄 if (to.meta.requiresAuth && !isUserLoggedIn()) { // 如果需要認(rèn)證且用戶(hù)未登錄,則重定向到登錄頁(yè) next('/login'); } else if (to.meta.requiresAdmin && !isUserAdmin()) { // 如果需要管理員權(quán)限且用戶(hù)不是管理員,則重定向到無(wú)權(quán)限頁(yè)面 next('/403'); } else { // 否則允許訪問(wèn) next(); } } } ]; const router = new Router({ routes });
在上面的示例中,我們定義了一個(gè)路由獨(dú)享守衛(wèi),它會(huì)在進(jìn)入/admin
路由前檢查用戶(hù)是否登錄和是否具備管理員權(quán)限。如果需要認(rèn)證且用戶(hù)未登錄,則重定向到登錄頁(yè);如果需要管理員權(quán)限且用戶(hù)不是管理員,則重定向到無(wú)權(quán)限頁(yè)面。
四、組件內(nèi)守衛(wèi)
組件內(nèi)守衛(wèi)是在組件內(nèi)定義的守衛(wèi),它分為beforeRouteEnter、beforeRouteUpdate和beforeRouteLeave。
- beforeRouteEnter
在進(jìn)入路由前執(zhí)行,可以在這里進(jìn)行數(shù)據(jù)預(yù)加載等操作。由于組件實(shí)例在守衛(wèi)執(zhí)行時(shí)還未被創(chuàng)建,因此不能訪問(wèn)this??梢酝ㄟ^(guò)將回調(diào)傳遞給next函數(shù)來(lái)訪問(wèn)組件實(shí)例。
示例代碼:
export default { name: 'MyComponent', beforeRouteEnter(to, from, next) { // 在進(jìn)入路由前執(zhí)行數(shù)據(jù)預(yù)加載等操作 console.log('準(zhǔn)備進(jìn)入MyComponent組件'); next(vm => { // 訪問(wèn)組件實(shí)例 vm.fetchData(); }); }, methods: { fetchData() { // 數(shù)據(jù)加載邏輯 console.log('加載數(shù)據(jù)'); } } };
在上面的示例中,我們?cè)赽eforeRouteEnter守衛(wèi)中進(jìn)行了數(shù)據(jù)預(yù)加載操作,并通過(guò)回調(diào)訪問(wèn)了組件實(shí)例以調(diào)用數(shù)據(jù)加載方法。
- beforeRouteUpdate
在當(dāng)前路由改變時(shí)執(zhí)行,但組件實(shí)例被復(fù)用。這可以用于響應(yīng)路由參數(shù)的變化。
示例代碼:
export default { name: 'MyComponent', beforeRouteUpdate(to, from, next) { // 在路由變化時(shí)執(zhí)行數(shù)據(jù)更新等操作 console.log('MyComponent組件的路由正在更新'); this.fetchData(); // 調(diào)用數(shù)據(jù)更新方法 next(); }, methods: { fetchData(params) { // 根據(jù)新的路由參數(shù)加載數(shù)據(jù) console.log('根據(jù)新參數(shù)加載數(shù)據(jù)'); } } };
注意:在上面的示例中,我們假設(shè)fetchData方法可以接受參數(shù),但beforeRouteUpdate守衛(wèi)并沒(méi)有直接傳遞參數(shù)給fetchData方法。在實(shí)際應(yīng)用中,你可能需要根據(jù)路由參數(shù)的變化來(lái)動(dòng)態(tài)加載數(shù)據(jù),這時(shí)你可以在beforeRouteUpdate守衛(wèi)中獲取新的路由參數(shù)并傳遞給fetchData方法。
- beforeRouteLeave
在離開(kāi)當(dāng)前路由前執(zhí)行,可以用于提示用戶(hù)是否確認(rèn)離開(kāi)當(dāng)前頁(yè)面。
示例代碼:
export default { name: 'MyComponent', data() { return { hasUnsavedChanges: false // 用于標(biāo)識(shí)是否有未保存的更改 }; }, beforeRouteLeave(to, from, next) { // 在離開(kāi)當(dāng)前路由前執(zhí)行確認(rèn)操作 if (this.hasUnsavedChanges) { // 提示用戶(hù)是否確認(rèn)離開(kāi) const answer = window.confirm('你有未保存的更改,確認(rèn)離開(kāi)嗎?'); if (answer) { next(); // 用戶(hù)確認(rèn)離開(kāi),允許導(dǎo)航 } else { next(false); // 用戶(hù)取消離開(kāi),阻止導(dǎo)航 } } else { next(); // 沒(méi)有未保存的更改,允許導(dǎo)航 } } };
在上面的示例中,我們?cè)赽eforeRouteLeave守衛(wèi)中檢查是否有未保存的更改,并提示用戶(hù)是否確認(rèn)離開(kāi)。如果用戶(hù)確認(rèn)離開(kāi),則允許導(dǎo)航;否則,阻止導(dǎo)航。
到此這篇關(guān)于Vue-Router路由守衛(wèi)詳?shù)募?xì)用法教程的文章就介紹到這了,更多相關(guān)Vue-Router路由守衛(wèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
區(qū)分vue-router的hash和history模式
這篇文章主要介紹了區(qū)分vue-router的hash和history模式,幫助大家更好的理解和學(xué)習(xí)vue路由,感興趣的朋友可以了解下2020-10-10vue實(shí)現(xiàn)自定義表格工具擴(kuò)展
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)自定義表格工具擴(kuò)展,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04解決微信瀏覽器緩存站點(diǎn)入口文件(IIS部署Vue項(xiàng)目)
這篇文章主要介紹了解決微信瀏覽器緩存站點(diǎn)入口文件(IIS部署Vue項(xiàng)目),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06Vue 中文本內(nèi)容超出規(guī)定行數(shù)后展開(kāi)收起的處理的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue 中文本內(nèi)容超出規(guī)定行數(shù)后展開(kāi)收起的處理的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04關(guān)于ElementUI el-table 鼠標(biāo)滾動(dòng)失靈的問(wèn)題及解決辦法
這篇文章主要介紹了關(guān)于ElementUI el-table 鼠標(biāo)滾動(dòng)失靈的問(wèn)題及解決辦法,本文給大家分享問(wèn)題所在原因及解決方案,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08undefined是否會(huì)變?yōu)閚ull原理解析
這篇文章主要為大家介紹了undefined是否會(huì)變?yōu)閚ull原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Vue 后臺(tái)管理類(lèi)項(xiàng)目兼容IE9+的方法示例
這篇文章主要介紹了Vue 后臺(tái)管理類(lèi)項(xiàng)目兼容IE9+的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02