這篇文章也發在我的部落格,歡迎圍觀?
寫在前面
前後端分離後,控制路由跳轉的責任轉移到了前端,後端只負責給前端返回一個html文件以及提供各種介面。下面我們用作例子的兩個專案,均採用vue作為基礎框架,一個是SPA應用,另一個是多頁應用,均由前端進行路由控制及渲染的。
總體思路
無論單頁還是多頁,我的實現思路是總體配置404頁面的思路就是在前端路由表中新增一個path: '/404'
的路由,渲染相應的404頁面。同時,配置一個規則,當在使用者可訪問的路由表中的所有路由都無法匹配的時候,自動跳轉重定向至該404頁面。下面來說一下針對單頁和多頁,我不同的實現方式。
SPA的404路由配置
單頁應用配置404頁面,也區分兩種情況:
路由表固定的情況
如果SPA的路由表是固定的,那麼配置404頁面就變得非常的簡單。只需要在路由表中新增一個路徑為404
的路由,同時在路由表的最底部配置一個路徑為*
的路由,重定向至404路由即可。
(由於路由表是由上至下匹配的,一定要將任意匹配規則至於最底部,否則至於此路由規則下的路由將全部跳轉至404,無法正確匹配。)
// router.js
export default new Router({
mode: 'history',
routes: [
// ...
{
name: '404',
path: '/404',
component: () => import('@/views/notFound.vue')
},
{
path: '*', // 此處需特別注意至於最底部
redirect: '/404'
}
],
})
複製程式碼
路由表動態生成的情況
路由表是動態生成的情況下,也就是說路由表分為兩部分,一部分為基礎路由表,另一部分是需要根據使用者的許可權資訊動態生成的路由表。
本專案中動態生成路由採用vue-router自帶的addRoutes方法,該方法是會將新的路由規則在原路由表陣列的尾部注入的。由於任意匹配重定向至404頁面的規則必須至於路由表的最底部,所以此處我將重定向至404頁面的規則抽出,在動態路由注入後,再注入重定向規則,以確保該規則至於路由表最底部。
// router.js
export default new Router({
mode: 'history',
routes: [
// ...
{
name: '404',
path: '/404',
component: () => import('@/views/notFound.vue')
},
// ...other codes
],
})
複製程式碼
// notFoundRouterMap.js
export default [
{
path: '*',
redirect: '/404'
}
]
複製程式碼
// main.js
//...other codes
router.beforeEach((to, from, next) => {
new Promise((resolve, reject) => {
if (getCookie(tokenName)) {
if (!getInfo()) {
Promise.all([store.dispatch('getBasicInfo'), store.dispatch('getUserDetail')]).then(res => {
store.dispatch('GenerateRoutes', { roles }).then(() => {
// 根據使用者許可權生成可訪問的路由表
router.addRoutes(store.getters.addRouters) // 動態新增可訪問路由表
router.addRoutes(NotFoundRouterMap) // 新增404及重定向路由規則
resolve({ ...to, replace: true }) // 重新載入一次路由,讓路由表更新成功後走下面else的判斷
})
})
} else {
// ...other codes
}
} else {
window.location.href = '/login.html'
}
}).then(res => {
if (res) {
next(res)
} else {
next()
}
}).catch(err => {
new Error(err)
next(false)
})
複製程式碼
多頁應用的404路由配置
多頁應用區別於SPA的不同點是每個頁面有自己的一套路由,並且每個頁面可能有自己的一套404頁面風格,當然也可能沒有。這時候,就不能再採用動態新增路由規則的方法了。
我採用的方案是在全域性導航守衛beforeEach中對路由匹配的情況進行判斷,這時候就需要用到vue導航守衛中的matched
陣列了。如果沒有一個匹配上的,那麼就重定向至404頁面。當然,這個404頁面也單獨設定為一個頁面。
// permission.js
//...other codes
router.beforeEach((to, from, next) => {
new Promise((resolve, reject) => {
// ...other codes
}).then(res => {
if (!to.matched.length) {
window.location = '/error.html#/404'
return
}
if (res) {
next(res)
} else {
next()
}
}).catch(err => {
new Error(err)
next(false)
})
複製程式碼
這個方案就允許每個頁面有自己的404頁面路由規則,並且為沒有配置404頁面的路由統一配置了預設的404頁面,感覺還是比較友好的。
最後
這是本人開發過程中使用的方案,如果有更好的方法,請不吝告知,謝謝!
在做這個實踐的時候,借鑑了不少兄弟的文章,在此列出,以表感謝!