路由管理

1.前言

  • 路由分为静态路由和动态路由,静态路由由前端直接写死,优点是简单方便,但是权限控制有漏洞,用户可以输入目标url强行访问没有权限的页面,而动态路由就可以避免这个问题,但是需要和后端数据对接,一般接口返回的数据需要转换后才能进行注册,注册后的页面才能进行访问,这个就避免了强行访问的问题

2.页面分类

  • 页面分为3种:固定页面,管理页面(带左侧和顶部的导航,主内容取才是真正的内容),和全屏页面
  • 固定页面:登录页,修改密码页面等,无需权限就能访问的页面
  • 管理页面:使用嵌套路由进行渲染,分为两层,第一层统一渲染布局组件(左侧和顶部的导航),第二次才渲染真正的页面组件,其中第一层路由是虚的,本身没有实质内容,他只能强制性重定向它的一个子路由
  • 全屏页面:使用一级路由进行注册,直接渲染该页面组件,一般不做权限管理
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)


//导航组件
const Layout = () => import('@/layout/index.vue')
//404页面
const Not_found = () => import('@/views/404.vue')

//静态路由
export const constantRouterMap = [
    { 
        path: '/',  component: Layout, redirect: '/dashboard' ,
        meta: {
            
        },
        children: [
            {
                path: 'dashboard', name: 'dashboard', component: () => import('@/views/dashboard/index.vue'),
                meta: {
                    
                },
            }
        ]
    },
    { 
        path: '/login', name: 'login', component: () => import('@/views/login/index.vue'),
        meta: {
            needLogin: false,//无需登录
        }
    },
]

//创建路由
const router = new VueRouter({
    routes: [
        ...constantRouterMap
    ]
})

//导出
export default router
  • 注意:左侧和顶部的导航是公共组件,可以有其他处理方式进行条件渲染,但是不建议。例如在fasatdmin中在url后面通过传参?tab=1来控制渲染,有这个参数,则渲染左侧和顶部的导航,没有这个参数,则全屏渲染页面。但是在vue中会引发其他问题,首先tab参数不好挂载,因为url路径使用的是hash,跟传统的网页url不一样,解析这个tab参数需要特殊处理,其次也是最重要的,路由跳转时,会覆盖整个hash的值,导致这个tab参数丢失,除非又要特殊处理,但是这样的话就不值当了

3.动态路由

  • 动态路由:调接口从服务器拿到可访问的页面列表进行动态路由注册
  • 全屏页面:调用addRoute()方法,需要传入路由路径,路由名称,代码文件路径
addPage(){
      this.$router.addRoute({
        path: '/newPage',//一级路由推荐使用绝对路径配置
        name: 'newPage',
        component: () => import('./views/newPage.vue')
      })
    }
  • 管理页面:调用addRoute()方法,除了需要传入路由路径,路由名称,代码文件路径,还需要父级路由的名称
addChildPage(){
      this.$router.addRoute('parentPage',{
        path: 'newPage',//嵌套路由推荐使用相对路径配置
        name: 'newPage',
        component: () => import('./views/newPage.vue')
      })
    }

4.菜单与路由

  • 一般通过权限管理来控制可访问的页面,路由规则和菜单展示他们共用一套数据
  • 每个权限节点都需要以下字段:名称,路径,子节点,是否全屏,路径可以将路由路径和文件路径进行统一
  • 菜单渲染需要的是树形节点的数据,而路由注册需要一维数组的数据,可分开进行处理
  • 注册路由时,需要移除菜单目录节点,只留下页面节点
  • 通过 是否全屏 这个节点来控制路由的注册是一级路由还是嵌套路由,注册嵌套路由时,自动裁剪当前路径作为路由的父节点,并自动注册此父节点路由,接着才注册嵌套路由
  • 一级路由要设置name属性,以便添加嵌套路由,嵌套路由可以不设置name属性
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  data() {
    return {
      whiteList: ['/login'],//白名单
      meneList: []
    }
  },
  watch: {
    '$route.path': {
      immediate: true,
      handler: function(newVal){
        //当前路径是否需要动态权限(白名单除外)
        if(!this.whiteList.includes(newVal) && this.meneList.length == 0){
          //模拟获取后台菜单
          this.getMenuList()
        }
      }
    }
  },
  methods: {
    //获取菜单
    getMenuList(){
      this.meneList = [
        {
          id: 1,
          title: "常用分类",
          path: "/category/index",
          fullView: 1,
        },
        {
          id: 2,
          title: "供应商管理",
          path: "/supplier/index",
          fullView: 1,
        },
        {
          id: 3,
          title: "物料分类",
          path: "/material/category",
          fullView: 0,
        },
        {
          id: 4,
          title: "物料档案",
          path: "/material/archives",
          fullView: 0,
        }
      ]
      //注册路由
      this.initRouter()
    },
    //注册路由
    initRouter(){
      //页面组件根目录
      var rootPath = "./views"
      //遍历菜单节点
      this.meneList.forEach(item=>{
        //判断是否是全屏节点
        if(item.fullView == 1){
          //一级路由
          this.$router.addRoute({
            path: item.path,
            component: () => import(`${rootPath}${item.path}`)
          })
        }else{
          //嵌套路由

          //一级路由
          var name = this.getParentName(item.path)
          //一级路由是否一级存在
          var allRoutes = this.$router.getRoutes()
          var hasRegister = allRoutes.some(item=>{
            return item.name == name
          })
          //先注册一级路由,再注册嵌套路由
          if(!hasRegister){
            this.$router.addRoute({
            path: '/' + name,
            name: name,
            component: () => import('./layout/index.vue')
          })
          }
          //注册二级路由
          this.$router.addRoute(name, {
            path: item.path,
            component: () => import(`${rootPath}${item.path}`)
          })
        }
      })
    },
    //获取一级路由的名称
    getParentName(path){
      var list = path.split('/').filter(item=>{
        return item
      })
      return list[0]
    },

  }
}
</script>

posted @   ---空白---  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示