需求:左侧的菜单栏渲染数据从路由文件中获取并组织成我们想要的数据格式。

路由:router》index.ts

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
    redirect:"order",
    children: [
      {
        path: 'order',
        name: 'order',
        meta:{isShow:true,title:"订单列表"},
        component: () => import('../views/OrderList.vue'),
      },
      {
        path: 'user',
        name: 'user',
        meta:{isShow:true,title:"用户列表"},
        component: () => import('../views/UserList.vue'),
      },
    ]
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  },
  {
    path: '/login',
    name: 'login',
    component: () => import( '../views/Login.vue')
  }
]

渲染菜单:

1、组织数据:

<script lang="ts">
import { defineComponent } from "vue";
import { useRouter, useRoute } from "vue-router";
export default defineComponent({
  name: "HomeView",
  components: {},
  setup() {
    const router = useRouter();
    const route = useRoute();
    // 获取到isShow为true的路由列表动态渲染菜单
    const routerList = router.getRoutes().filter((v) => v.meta.isShow);
    return {
      routerList,
      active: route.path,
    };
  },
});
</script>

2、使用element-plus的Menu组件进行展示:

  • el-menu组件要开启路由模式:router
  • 要添加  <router-view />
    <el-container>
      <el-aside width="200px">
        <el-menu
          router
          active-text-color="#ffd04b"
          background-color="#545c64"
          class="el-menu-vertical-demo"
          :default-active="active"
          text-color="#fff"
        >
          <el-menu-item v-for="i in list" :key="i.path" :index="i.path">
            <el-icon><icon-menu /></el-icon>
            <span>{{ i.meta.title }}</span>
          </el-menu-item>
        </el-menu>
      </el-aside>
      <el-main>
        <router-view />
      </el-main>
    </el-container>

效果:

此代码只适用一级菜单,多级菜单也是这个思路组织好数据然后再渲染。

这个其实不完全算是动态的路由,动态的路由其实应该是后端根据当前用户信息返回的路由。

可以在路由拦截里从后台获取路由数据并添加到路由里:

// 路由拦截
router.beforeEach(async to => {
  const token:string | null = localStorage.getItem('token')
  if (!token && to.path !== '/login') {
    // 若没有登录且去的不是登录页面,强制用户登录
    return '/login'
  } else if (token && to.path !== '/login/') {
    // 如果登陆过了且不去登录页面,并且之前没有加载过菜单,那么要加载菜单
    if (router.getRoutes().length === 3) {
      // 请求后台接口获取路由【同步】
      let routerData:any = await getRouter()
      routerData = routerData.data
      routerData.forEach((v:any) => {
        const routerObj:RouteRecordRaw = {
            path:v.path,
            name:v.name,
            meta: v.meta,
            component:()=>import(/* webpackChunkName: "[request]" */ `../views/${v.path}.vue`)
        }
        //将路由节点添加到home的children中
        router.addRoute("home",routerObj)
      })
      router.replace(to.path)
    }
  } else if (token && to.path === "/login") {
    return '/'
  }
})

Logo

前往低代码交流专区

更多推荐