写在前面
前后端分离后, 控制路由跳转的责任转移到了前端, 后端只负责给前端返回一个 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 [
- {
- name: '404',
- path: '/404',
- component: () => import('@/views/notFound.vue')
- },
- },
- {
- 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 页面, 感觉还是比较友好的.
最后
这是本人开发过程中使用的方案, 如果有更好的方法, 请不吝告知, 谢谢!
在做这个实践的时候, 借鉴了不少兄弟的文章, 在此列出, 以表感谢!
基于 Vue2.0 实现后台系统权限控制
用 addRoutes 实现动态路由 https://refined-x.com/2017/09/01/用addRoutes实现动态路由/
how to create a 404 component in vuejs using vue-router https://stackoverflow.com/questions/45619407/how-to-create-a-404-component-in-vuejs-using-vue-router
来源: https://juejin.im/post/5b019ad7f265da0ba567d259