美文网首页
【vue-router】项目设计

【vue-router】项目设计

作者: 嘻洋洋 | 来源:发表于2021-11-17 17:31 被阅读0次

    下面介绍在实际项目中使用vue-router,整体规划设计

    1. 规划内容

    (1)核心的几个关键路由:登录页面,主页,错误页面。
    (2)页面访问控制:有些页面不需要做登录控制
    (3)动态路由:模块菜单有一部分是数据库配置的,因此除了固定路由外,有一部分是动态添加的路由

    2. 详细设计

    2.1 全局路由

    全局路由指独立的,不需要验证是已登录的页面,不需要用到导航卫士,不需要使用嵌入Main框架:比如登录页,错误页,外部系统调用的页面(通过签名授权)

    // 全局路由(无需嵌套上左右整体布局)
    const globalRoutes = [
      { path: '/404', component: _import('common/404'), name: '404', meta: { title: '404未找到' } },
      { path: '/login', component: _import('common/Login'), name: 'login', meta: { title: '登录' } },
      { path: '/', component: _import('common/Login'), name: 'first', meta: { title: '登录' } },
      { path: '/scm2erp/consignmentPurchaseInvoice', component: _import('modules/erp/scm_settlement/consignment_purchase_invoice/ConsignmentPurchaseInvoice'), name: 'consignmentPurchaseInvoice', meta: {title: '代销买入发票'}},
      { path: '/scm2erp/dxInputInvoice', component: _import('modules/erp/scm_settlement/consignment_purchase_invoice/DxInputInvoice'), name: 'dxInputInvoice', meta: {title: '代销录入发票'}},
    ]
    

    2.2 Main路由

    (1)路由设计
    Main路由就是登录后进入的首页,在这个首页里面同时 (同级) 展示多个组件,比如有MainNavbar (顶部), MainSidebar (侧导航) 和 MainContent (主内容) 。其中MainNavbar和MainSidebar是常规组件。MainContent是嵌套视图组件【Main的子组件】,所有页面显示在其中(含有路由的出口)。Main本身也是一个视图组件。

        <template v-if="!loading">
          <main-navbar />
          <main-sidebar />
          <div class="site-content__wrapper" :style="{ 'min-height': documentClientHeight + 'px' }">
            <main-content v-if="!$store.state.common.contentIsNeedRefresh" />
          </div>
        </template>
    //  引入视图组件
    import MainNavbar from './MainNavbar'
    import MainSidebar from './MainSidebar'
    import MainContent from './MainContent'
    
      components: {
        MainNavbar,
        MainSidebar,
        MainContent
      },
    

    因此设计成嵌套路由

    // 主入口路由(需嵌套上左右整体布局)
    const mainRoutes = {
      path: '/',
      component: _import('Main'),
      name: 'main',
      redirect: { name: 'home' },
      meta: { title: '主入口整体布局' },
      // 固定路由
      children: [
        { path: '/home', component: _import('common/Home'), name: 'home', meta: { title: '首页' } },
        { path: '/theme', component: _import('common/Theme'), name: 'theme', meta: { title: '主题' } },
        { path: '/supplier_settlement-OutAccountAudit', component: _import('modules/erp/sup_settlement/OutAccountAudit'), name: 'supplier_settlement-OutAccountAudit', meta: { title: '供应商出账数据稽核', isTab: true } }
       ]
    }
    

    在Main主路由中的所有页面的嵌套路由分两种,一种是如上的固定路由,不属于菜单,不通过数据库配置。
    另外一种是动态路由,如通过数据库配置的菜单,因此需要动态添加路由:

    //路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。因此另外取一个名字
        mainRoutes.name = 'main-dynamic'
        mainRoutes.children = routes
        router.addRoutes([
          mainRoutes,
          { path: '*', redirect: { name: '404' } }
        ])
    // 为了避免刷新后清空,需要本地先存
        sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]'))
    

    (2)访问控制
    访问Main路由之前,验证是否已经登录成功,因此Main路由这里使用路由独享的守卫,如:

      beforeEnter (to, from, next) {
        let token = Vue.cookie.get('token')
        if (!token || !/\S/.test(token)) {
          clearLoginInfo()
          next({ name: 'login' })
        }
        next()
      }
    

    2.3 全局守卫

    访问路由前,如果请求的路径不是全局路由,并且没有添加动态路由,需要重新加载路由后,继续访问,目的解决刷新问题导致动态路由丢失。

    router.beforeEach((to, from, next) => {
      if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') {
         next()
      } else {
        http({
          url: http.adornUrl('/sys/menu/nav'),
          method: 'get',
          params: http.adornParams()
        }).then(({ data }) => {
          if (data && data.code === 0) {
            fnAddDynamicMenuRoutes(data.menuList)
            router.options.isAddDynamicMenuRoutes = true
            sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]'))
            sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
            next({ ...to, replace: true })
          } else {
            sessionStorage.setItem('menuList', '[]')
            sessionStorage.setItem('permissions', '[]')
            next()
          }
        }).catch((e) => {
          console.log(`%c${e} 请求菜单列表和权限失败,跳转至登录页!!`, 'color:blue')
          router.push({ name: 'login' })
        })
      }
    })
    

    3. 其它设计

    3.1 根路径匹配多个路由

    登录页面要使用根路径,Main路由也使用根路径,目的为是以 / 开头的嵌套路径会被当作根路径。 充分的使用嵌套组件而无须设置嵌套的路径。由于同一个路径可以匹配多个路由,所以是可以实现的,同时要把登录页面路由放在Main路由前面。当路径匹配到多个路由时,优选匹配前面的。

    3.2 匹配任意路径

    对应输入错误地址时,我们不希望显示404,能够显示相应错误页面。因此路由最后面添加一个对于所有路径都能匹配一个的路由。当匹配不到路由,就匹配错误页面路由。

        router.addRoutes([
          mainRoutes,
          { path: '*', redirect: { name: '404' } }
        ])
    

    相关文章

      网友评论

          本文标题:【vue-router】项目设计

          本文链接:https://www.haomeiwen.com/subject/jaicgltx.html