从git上拉下之前的Vue项目,运行后,并通过源码的研读,发现一些问题,这些问题促使势必要对代码要做出一些改动,Vue的核心架构,按照官方解释和个人理解,主要在于组件和路由两大模块,只要理解了这两大模块的思想内容,剩下API使用就只是分分钟的事情了。

首先从路由来讲,之前老的Vue项目路由这里
old vue router

可以看出,根据不同的模块将路由拆分成不同的文件夹,每个文件夹相当于一级菜单,文件夹下有 index.js,在这个js中声明了这个一级菜单有哪些子菜单即二级菜单,然后新建二级菜单文件夹,里面又有一个 index.js 声明了二级菜单。每个js中都会调用下面 common.js 中 checkName 方法通过接口返回的 isHidden 来确认菜单是否显示。这样看会显得稍微繁琐,并且有个致命的问题,那就是登录后,这些菜单路由会发出异步请求,就上面那些文件夹就足足有29个请求,哪怕是没有的菜单,只是新建了文件夹及文件而已。会使得登录后出现短暂的空白才会显示出侧边菜单栏,并且在没有三级菜单前提下。
首先改动这里的路由文件
new vue router

可以看出改动后的路由只需要一个文件,并且一个文件中,就配置了菜单项,不管是一级还是二级、三级都可以,同时通过这个路由文件将权限给到了前端,在这里引申出一个命题:权限是由前端or后端控制?

常见的项目路由表是由后端根据用户的权限动态生成的。即用户登录后拿到用户的信息,通过信息中这个用户的角色(权限)去角色菜单表中,关联查询,这个角色可以看到那些菜单,返回一个整体的菜单表,即最简单的 rbac 权限验证。我在这里之所以把这个权限给了前端,而没有采取之前的方式,原因如下:

  • 项目不断的迭代你会异常痛苦,前端新开发一个页面还要让后端配一下路由和权限,或者之前前端页面的嵌套是 php 嵌套的,前端拿到 ui 后会新建一个单独的 html 及单独的 css 给到你,然后你再整合进去
  • 其次现在后端通常运用api来实现项目,不再直接操作数据库,前后端的权限划分是不一样的,前端可以控制用户是否可以看这个菜单,而后端更多的是按钮级别的权限控制,即用户点击添加按钮后,后端可以通过角色和 api 的对照表,检测这个用户是否有 addApi 的权限,以此来杜绝用户按钮操作的越权问题,之前都是不断地if,else判断来显示隐藏这些按钮,非常麻烦!
  • 还有一点是就 vue2.2.0 之前异步挂载路由是很麻烦的一件事!不过好在官方也出了新的 api,即 addRoutes

言归正传,这个 index.js 的具体实现

  1. 创建 vue 实例的时候将 vue-router 挂载,但这个时候 vue-router 挂载一些登录或者不用权限的公用的页面。
  2. 当用户登录后,获取用 role,将 role 和路由表每个页面的需要的权限作比较,生成最终用户可访问的路由表。
  3. 调用 router.addRoutes(store.getters.addRouters) 添加用户可访问的路由。
  4. 使用 vuex 管理路由表,根据 vuex 中可访问的路由渲染侧边栏组件。

所有权限通用的路由表,如首页,登录页和一些不用权限的公用页面
constant router

异步挂载的路由,动态需要根据权限加载的路由表
async router

这里我们根据 vue-router官方推荐的方法 通过meta标签来表示该页面能访问的权限有哪些。如 meta: { role:['admin','development'] } 表示该页面只有admin和开发才能有资格进入。

这里有一个需要非常注意的地方就是404页面一定要最后加载,如果放在 constantRouterMap 一同声明了404,后面的所有页面都会被拦截到404,详细的问题见
addRoutes when you've got a wildcard route for 404s does not work

而且这里定义路由的时候添加了一些参数:

icon : the icon show in the sidebar
hidden : if hidden:true will not show in the sidebar
redirect : if redirect:noredirect will not redirct in the levelbar
noDropdown : if noDropdown:true will not has submenu
meta : { role: ['admin'] } will control the page role

关键的permission.js,即前端权限控制的部分,我放在src根目录下与main.js并排
permission

因为我登陆后并不会拿到用户信息,而是返回一个token,存入cookie中,在这里使用了 store 即 vuex,个人建议不要为了用vuex而用 vuex。因为我做的这个BI数据查询看似业务很庞大,要查询各种数据,但业务之间耦合度非常低,几乎都是独立的模块,所以根本就没有必要使用 vuex 来存储 data,每个页面存储自己的data即可,当然有些数据还是需要用 vuex 来统一管理的,如登录token,用户信息,或者是一些全局个人偏好设置等,还是用 vuex 管理更加的方便,具体当然还是要结合自己的业务场景的。总之还是那句话,不要为了用 vuex 而用 vuex!

再扯回话题,登录后获得一个token存入cookie,这里的 token 每次登录后都会返回一个新的,变相的算是一个单设备登录,当别人使用相同的账户登录后,你会被踢下线。每一次的请求都会带着这个 token 也算做了一个最基本的安全验证了。逻辑见注释!重点来看下 GenerateRoutes 这个方法,我放在 store 文件里 modules 文件夹下
generate routes

这里的代码说白了就是干了一件事,通过用户的权限和之前在index.js里面asyncRouterMap的每一个页面所需要的权限做匹配,最后返回一个该用户能够访问路由有哪些。

最后一个涉及到权限的地方就是侧边栏,不过在前面的基础上已经很方便就能实现动态显示侧边栏了。这里侧边栏基于element-ui的NavMenu来实现的。说白了就是遍历之前算出来的permission_routers,通过vuex拿到之后动态v-for渲染而已。渲染的过程中判断下上面定义路由时加的一些参数。

至此路由改造完成,一个路由文件搞定,权限也交给了前端,与之前多文件夹,异步请求加载路由相比瘦身一大截!拿给我们leader演示后,探讨了下这个路由问题,除了去掉了那个异步请求加载路由以外,这个一个路由文件和多个文件夹路由各有优劣!我之前崇尚的极简的一个路由文件搞定适合个人开发,而到了以后人员更多业务也更多的时候势必需要协同开发,那个时候每个人做自己的一个模块,除了全局的一些数据,模块与模块之间是互不干涉的,极度解耦,这样多个文件夹路由就成了必然,而一个路由文件将产生很多麻烦!因为大家都修改一个文件,不管是git建立分支也好,svn合并也好,都会有一个merge过程,甚至产生冲突,而多个文件夹每个人修改自己的文件夹,则完全没有这个问题! 存在即合理

下面就是组件了,组件库是做UI和前端日常需求中经常用到的,把一个按钮,导航,列表之类的元素封装起来,方便日常使用,调用方法只需直接写上或者这样的代码就可以,是不是很方便呢!因为我不是专业的前端所以采用了Element UI,之所以选择它,因为它是基于Vue2.0的组件库,提供了配套的设计资源,而且开发者是饿了么的程序猿,持续更新应该会有一定的保障!

而在这里我的后台使用了PhalApi,因为我们团队是这个开源框架的贡献者和维护者之一。这个api开发框架追求的只有一个,那就是性能,超高的性能及超快的开发速度值得你拥有!

至此一个基于Vue+Vue-Router+Vuex+Element UI做前台,PhalApi做后台的BI查询基础版只需三天就问世了。这网页打开的速度很是让人酸爽哟!
sunmi bi

忽略上图中的样式风格,毕竟没有产品也没有设计,我就按自己的程序员审美来了,同时我也是Vue的初学者,接触Vue满打满算才两个星期,此篇文章只供自己回忆或他人一乐,说的哪里不对,请见谅!在此引用一句我很喜欢的话:

面对技术的高速发展和百花齐放,我有时也感到疲倦烦躁。但是,每当看到它们带来的生产力的飞跃,让你一个人快速搞定前后端的全部开发时,就觉得这终究还是一条正确的道路。

最后修改:2023 年 09 月 11 日
如果觉得我的文章对你有用,请随意赞赏