一个码农

一个菜鸟的日常搬砖记录 开始使用

尝试一种 vue 动态路由的实现方式。

一、说明

花了两天的时间,现学现用,对接手的项目中静态的路由修改为动态实现,所有菜单从数据库直接获取(因为菜单是要根据权限直接配置的),记录一下,以备后用。

二、准备环境

由于是已经开工的项目,基本就是在原本的环境上进行开发

  • vue 2.5.13
  • nodejs 9.3.0
  • npm 5.6.0

等等,反正其他的也没什么重要的,就不再提了,应该不会影响实现结果。

三、开工

3.1 为什么我要改为动态

  • 首先,动态路由的话,不用每个路由都写入到 router.js 里面(但是目前我的实现仍需要将所有的页面引用都写出来)
  • 可以根据不同的权限,直接从数据库查询出他能访问的菜单,无权访问的直接会被 404 拦截。而不用 if else 判断。
  • 路由信息存在数据库中,如果想要修改,直接改库就好了,便于维护

3.2 最初的设想

其实呢,一开始的时候,为是计划所有的东西都存在数据库,包括页面路径之类的,但是实际操作中无法动态引用文件,为猜是因为 vue 需要提前编译的缘故吧,动态引用文件开始的时候没有被编译进去(瞎猜的),总之为尝试了将下面这段代码里的页面地址改为变量,是无法加载到文件的

 component: (resolve) => require(['./views/sysManager/sysOrg/sysOrg.vue'], resolve)
 //比如为改为下面这种,是不行的
 let url = './views/sysManager/sysOrg/sysOrg.vue';
 component: (resolve) => require([url], resolve)

先别在意变量是不是这样用的,因为为尝试了很多中用法,并且请教了以前前端的同事,最后都以失败告终。

3.3 退而求其次

为想把所有东西都存数据库,前端完全不用太多多余操作的想法最终是没实现,问题就出在,动态加载页面文件的时候加载不到。那么我只要先把这些文件全部加载了(不知道会不会影响性能,反正我是这么做了),然后在把引用的名字存在数据库,到了前端,直接拿名字取这个引用的文件就好了。

3.3 直接上代码

3.3.1 登陆以后取获取菜单

getRouter(data){
    var params = {
        loginName:data.result.userInfo.userAccount
  };
  getRouter().then(rs => { //这个getRouter() 其实是一个ajax 请求,我们的项目把ajax 请求写在统一的地方了,
        console.log('从后台获取到以后是什么格式')
        console.log(rs.data.result)
        this.$store.dispatch('setRouter', JSON.stringify(rs.data.result));
  });
}

这段代码比较简单,就是在登陆成功以后调用,从数据库查询菜单的 json 数据,然后把这些数据存储在vuex 里面。为了防止刷新以后就没有了,同时也存了一份在localStorage 里面

代码在 store.js 里面

3.3.2 对查询的路由信息进行缓存

SETROUTER(state,value){
    state.routers = value;
  localStorage.setItem('routers', value);
},

这里呢,是把查询到的路由信息分别存储在vuexlocalStorage 中,每次刷新页面以后,从 localStorage 中 取出来重新存进 vuex 里面。

3.3.3 从 vuex 中获取路由并添加到 vue 路由里面

let routers = store.state.routers;
if (routers !== null && routers !== 'undefined'){
    let routersArray = JSON.parse(routers)
    //遍历父节点
  routersArray.forEach((router)=>{
        let childrens = router.childrens
        let component = router.componentName;
  //遍历子节点
  let childrenArray = [];
  childrens.forEach((children) => {
            let childrenObject = {
                path:children.path,
  component:fullpath[children.componentName],
  name:children.name,
  iconCls:children.iconCls,
  };
  childrenArray.push(childrenObject)
        });
  routes.push(
            {
                path: router.path,
  component:fullpath[component],
  name:router.name,
  iconCls:router.iconCls,
  children:childrenArray
            }
        )
    })
}
//将404 在其他路由的后面加入,以保证每一个没有在路由列表里的path 都被404 拦截
routes.push(
    {
        path: '/*',
  component: fullpath['NotFound'],
  name: '404',
  hidden: true
  }
)
const router = new VueRouter({
    routes
})

这里呢,routersArray 就是后台返回的数组,遍历 push 到 路由的 routes 数组里面,需要说的是这里在后面写了404 路由,因为404 要在蕞后面,才能保证 正常拦截并展示404 页面,再最后,再初始化 VueRouter,这样,生成的路由就是我们动态的了。

注意:上面代码中,component 是做了一个引用,将所有的文件都提前加载了,代码如下
9bf3808960a840218c3fe786319edda6-image.png

3.3.4 现在 router.js 里面就不需要写太多东西了

a906cbf11fab4f4587f140505d8d2d43-image.png

除了 import 的文件,这就是 router.js 里面的所有内容了,而且以后新增页面也不需要再修改这个文件了。

四、后话

由于家里的事多,工作不稳定,近两个月来都是四处奔波的,博客也有几个月没有写了。今天算一个新的开始,工作也稳定了,以后要坚持了。

毕竟一个服务端的程序员,基本很少写前端代码,希望哪里不对的,大神帮忙指正。

一个可菜可菜的码农

评论
留下你的脚步