Vue路由守卫优化: 我把老王的门锁换了

Vue路由守卫优化: 我把老王的门锁换了

正所谓一杯茶、一根烟、一段代码写一天,这天我正在工位上喝着我的蜂蜜柚子猫茶,就听到我隔壁工位上的老王隔一段时间,就发出 "唉" 的叹气声,几次循环之后,我就再也忍不住踱步过去看看头发都快要被薅秃的老王到底遇到了啥问题。

1. 过于臃肿的路由守卫

定睛一看,原来问题出在路由守卫这里

js 复制代码
router.beforeEach(async (to, from, next) => {
    if ((to.path == '页面A' || to.path == '页面B') && 用户是否登录) {
        next('登录页面')
    } 
    if ((to.path == '页面A' || to.path == '页面B') && 用户是否认证) {
        showDialog({
            confirm: () => {
                next('认证页面')
            }
        })
    }
    if ((to.path == '页面A' || to.path == '页面B') && 用户是否具有邮箱) {
        next('邮箱页面')
    }
});

可以看到该代码,很多判断都和页面绑定到了一起,导致每次有新页面需要拦截的话,都需要在这厚重的判断上再增加上新的代码,导致这块代码会越来越复杂,直到无法维护。

2. 优化路由守卫

那么该如何优化呢,我考虑从两个方面入手:

第一个: 将页面是否登录、认证之类的信息,放到路由本身的元信息中去,由路由本身来判断自己是否需要拦截,而不是写死在路由守卫中,而且这样做的好处是对于都需要拦截的子路由来说,只需要在父路由上携带是否需要拦截即可

第二个: 将所有拦截器统一到外部数组中,让拦截器和路由守卫本身分离,使得编写拦截器时不会再对路由守卫本身造成意料之外的影响,同时也不会让路由守卫这个方法本身变得过于复杂。

接下来直接上改造后的代码吧

js 复制代码
// 定义路由
const router = [
    {  
        path: '/xxx',  
        name: 'xxx',  
        component: () => import('xxx.vue'),
        meta: {
            // 是否需要登录
            requireLogin: true,
            // 是否需要邮箱
            requireEmail: true
        }
    },
    {  
        path: '/xxx',  
        name: 'xxx',  
        component: () => import('xxx.vue'),
        meta: {
            // 是否需要登录
            requireLogin: true,
            // 是否需要邮箱
            requireEmail: true
        },
        // 这样子路由也同样拦截了
        children: [
            {
                path: '/xxx',  
                name: 'xxx',  
                component: () => import('xxx.vue')
            }
        ]
    }
]

// 定义统一拦截器
const FILTER_LIST = [  
    {  
        name: '登录过滤器',  
        func: async (to, from) => { 
            if (!to.meta.requireLogin) {  
                return null;  
            }
            if (用户是否登录) {
                return '登录页面'
            }
        }  
    },
    {  
        name: '邮箱过滤器',  
        func: async (to, from) => { 
            if (!to.meta.requireEmail) {  
                return null;  
            }
            if (用户是否具有邮箱) {
                return '邮箱页面'
            }
        }  
    }
]

// 路由守卫
router.beforeEach(async (to, from, next) => {  
    let breakFilterResult = null;
    console.groupCollapsed('路由FILTER')
    console.log('------------------------ FILTER START ------------------------')
    // 循环拦截器,判断拦截器是否通过
    for (const filterItem of FILTER_LIST) {  
        const result = await filterItem.func(to, from);  
        if (result != null) {  
            breakFilterResult = result;  
            console.log('- ' + filterItem.name + '%c [不通过]', 'color:#f00;');
            // 如果拦截器没有通过,使用break跳出循环
            break;
        } else {  
            console.log('- ' + filterItem.name + '%c [通过]', 'color:#0f0;');  
        }  
    }
    console.log('------------------------ FILTER END ------------------------')
    console.groupEnd();  
    if (breakFilterResult != null) {  
        next(breakFilterResult);  
    } else {  
        next();  
    }  
});

3. 结语

很多时候简单就是复杂,复杂有时候却意味着简单,通过抽象和分离,看似代码变得更加复杂了,但是维护起来却其实变得更加简单了。当然代码编写有时候就是取舍之道,你不一定要做的多正确,很多时候你的优化和重构并不一定能让代码变得更好,但是一定要前进在让代码变好的路上。

相关推荐
前端大卫44 分钟前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友1 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理3 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻3 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
mapbar_front4 小时前
在职场生存中如何做个不好惹的人
前端
牧杉-惊蛰4 小时前
纯flex布局来写瀑布流
前端·javascript·css
一袋米扛几楼985 小时前
【软件安全】什么是XSS(Cross-Site Scripting,跨站脚本)?
前端·安全·xss
向上的车轮5 小时前
Actix Web适合什么类型的Web应用?可以部署 Java 或 .NET 的应用程序?
java·前端·rust·.net
XiaoYu20025 小时前
第1章 核心竞争力和职业规划
前端·面试·程序员
excel5 小时前
🧩 深入浅出讲解:analyzeScriptBindings —— Vue 如何分析 <script> 里的变量绑定
前端