硬件前端

如何根据后端返回的设备类型动态生成前端路由表

2020-03-23  本文已影响0人  千茉紫依

问题概述

最近在参与嵌入式设备前端项目, 这些设备通过挂载不同的传感器拥有不同的功能, 所以后台管理页面也不尽相同,这需要根据后端返回的功能列表来动态生成前端路由表.

由于项目直接套用的vue-cli脚手架, router类似这样在一开始就初始化写死了,而后端返回的routes则是在login页面里面通过axios去获取的,要等消息返回之后,用后端来的消息把路由表进行改写,以达到一套代码适应不同类型设备的要求.

new Vue({
  el: '#app',
  i18n,
  router,
  store,
  render: h => h(App)
})

路由表中是写死的,首页默认会重定向到diviceManage界面

const routes=[
    ...
    {
      path: '/',
      component: Layout,
      redirect: '/diviceManage'
    }
]
但是此时login的url已经生成,他拥有默认的重定向 首页的默认重定向

解决思路

最开始我试着这样,这时虽然可以用获取到的routes变量来改写前端路由表,点击登录依旧会跳到改之前设定的diviceManage界面,而不是新设定的newIndex,也就是说this.redirect = '/newIndex'设置了没有起作用

 const { cmd, routes } = response
 this.$router.options.routes = routes
 this.redirect = '/newIndex'

经过查找vue-router的issue, 发现这样一条https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const Routes=[...]

const createRouter = () => new Router({
  mode: 'history',
  routes: Routes
})

const router = createRouter()

export function resetRouter () {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // the relevant part
}

export default router

router.matcher对外提供两个方法match(负责route匹配),addRoutes(动态添加路由),当路由进行切换时,内部会调用match方法const route = this.router.match(location, this.current) 对原始路由和要跳转的路由进行比对, 其实内部会使用matcher来匹配routes,修改router.matcher属性,新的routes就会替换旧的routes

在Router中定义Router函数,将resetRouter导出,在改了路由表之后再用新的matcher替换旧的matcher,这样,即使浏览器上面的url导航还是指向的旧地址,但是登陆之后,就会直接到跳转到newIndex了

 const { cmd, routes } = response
 this.$router.options.routes = routes
 this.redirect = '/newIndex'
 resetRouter()

这就解决了根据后端消息动态生成前端路由的问题

下面解决路由表持续存储的问题,由于路由表实在登录前动态获取的,而后管系统众多页面,不可能每个页面都写这样一套逻辑,所以在获取到routes就要进行存储,然后在各个页面加载前调用,这就解决了刷新导致路由表失效问题

localStorage.setItem('routes', JSON.stringify(routes))

但这也额外引出了一个本地存储在何时更新的问题,我是这样设计的,在获取到routes,除了写入localStorage,也向vuex中写入同名的变量,将路由表添加到vuex中,这样在不刷新的情况下,这个路由信息可以持续使用, 这样写有很多好处:

  1. 仅在首次登录时,由于vuex中没有routes变量,会触发getRoutes请求动态生成路由表,在其他情况下进入登录界面,比如修改ip,升级,重启等被踢出登录,则不会触发getRoutes函数,能减少请求
  2. 在非登陆页面,由于没有首页的重定向问题,页面刷新直接调用localStorage.getItem('routes')获取路由表,能减少请求,提高响应速度
  mounted() {
    if (!this.$store.app.routes) {
         this.getRoutes()
    }
  },
   methods: {
       getRoutes(){
           ...
           const { cmd, routes } = response
           this.$router.options.routes = routes
           this.redirect = '/newIndex'
           resetRouter()
           this.$store.dispatch('app/setRoutes', routes)
           localStorage.setItem('routes', JSON.stringify(routes))
       }
   }
上一篇下一篇

猜你喜欢

热点阅读