话不多说,直接上代码,首先看看页面解构 (这里使用的是模拟import导入的数据)

 路由文件:router/index.ts

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import dataList from '../assets/data'   //模拟数据
import { defineAsyncComponent } from 'vue'
import { useCounterStore } from '@/stores/counter'  // 引入 pinia库

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'shouye',
      redirect: 'home'
    },
    {
      path: '/home',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('../views/AboutView.vue')
    }
  ]
})


// 前置路由守卫
router.beforeEach((to, from, next) => {
  const useCounter = useCounterStore()
  const nav = dataList.data.nav  //获取到路由数据


  // 方式1:通过pinia的confalse来判断是否是第一次加载页面,第一次的话,需要渲染路由和跳转到路径上的路由上,会执行两次
  // if (useCounter.confalse) {
  //   routeCallback(nav)
  //   useCounter.$patch({
  //     count: nav,
  //     confalse: false
  //   })

  //   next({ path: to.path })
  // } else {
  //   next()  // 后面只要不刷新页面就会正常跳转路由
  // }


  //---------------------------------------------------------------------------------------------------------


  // 方式二:首先加载路由,但是当前会多次加载路由
  routeCallback(nav)
  useCounter.$patch({
    count: nav,
    confalse: false
  })
  // 当前浏览页面数不少于0 或者 form的不等于 /
  if (to.matched.length > 0 || from.path !== '/') {
    next();
  } else {
    // 防止页面刷新  当上一次路由等于/ 并且 这次浏览记录为空的时候需要进入刷新前的页面
    if (from.path == '/' && to.matched.length <= 0) {
      next(to.path);
    } else {
      next('/404');
    }
  }


})

// 封装重复回调
function routeCallback(data: any) {
  data.forEach((item: any) => {
    if (item.children.length) {
      routeCallback(item.children)
    }

    let route: any = {
      name: item.name,
      path: item.path,
      meta: {
        icon: item.icon,
        title: item.title
      },
      component: (() => import(/* @vite-ignore */'../views/' + item.component + '.vue'))

      // 如果报错了用这个 vite特别需要的引入
      // component:()=> defineAsyncComponent(() => import(/* @vite-ignore */'../views/' + item.component + '.vue'))  
    }
    router.addRoute(route)
  })
}

export default router

 pinia文件:stores/counter.ts

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
  const count = ref({})
  const confalse = ref(true)

  return { count, confalse }
})

 pinia文件:stores/index.ts

import { createPinia } from 'pinia'
const pinia = createPinia()

export default pinia

main.ts

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import App from './App.vue'
import router from './router'
import pinia from './stores/index'

import './assets/main.css'
import 'element-plus/dist/index.css'

const app = createApp(App)


app.use(router)
app.use(pinia)
app.use(ElementPlus)

app.mount('#app')

App.vue

<template>
  <div class="app">
    <div class="left">
      <!-- 左侧导航栏 -->
      <el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="2" text-color="#fff" @open="handleOpen" @close="handleClose">
        <el-sub-menu index="1">
          <!-- 一级菜单内容 -->
          <template #title>Navigator One</template>
          <!-- 二级菜单 -->
          <el-sub-menu index="1-1">
            <!-- 二级菜单内容 -->
            <template #title>item four</template>
            <el-menu-item index="1-1-1">item one</el-menu-item>
          </el-sub-menu>
        </el-sub-menu>

        <!-- 动态路由加载 -->
        <el-sub-menu :index="item.name" v-for="item in count">
          <template #title>{{item.title}}</template>

          <router-link :to="item2.path" v-for="item2 in item.children" :key="item2.name">
            <el-menu-item :index="item2.name">
              <template #title>
                <i :class="item2.icon"></i>
                <span slot="title">{{item2.title}}</span>
              </template>
            </el-menu-item>
          </router-link>
        </el-sub-menu>

      </el-menu>
    </div>
    <div class="right">
      右侧视图
      <RouterView></RouterView>
    </div>
  </div>
</template>

<script setup lang="ts">
import { RouterLink, RouterView, useRoute } from "vue-router"; //引入路由
import { useCounterStore } from "@/stores/counter"; //引入pinia
import { storeToRefs } from "pinia";
import {
  Document,
  Menu as IconMenu,
  Location,
  Setting,
} from "@element-plus/icons-vue";
const handleOpen = (key: string, keyPath: string[]) => {
  console.log(key, keyPath);
};
const handleClose = (key: string, keyPath: string[]) => {
  console.log(key, keyPath);
};

const route = useRoute();
const useCounter = useCounterStore();
const { count } = storeToRefs(useCounter);

// console.log(count);
</script>

<style scoped>
.app {
  display: flex;
  width: 100%;
  height: 100vh;
}
.left {
  width: 20%;
  background-color: #545c64;
  height: 100vh;
}
.right {
  flex: 1;
}
</style>

数据文件:assets/data.js

export default {
  "code": 200,
  "msg": "操作成功",
  "data": {
    "nav": [
      {
        "id": 1,
        "title": "系统管理",
        "icon": "el-icon-s-operation",
        "path": "",
        "name": "sys:manage",
        "component": "",
        "children": [
          {
            "id": 2,
            "title": "用户管理",
            "icon": "el-icon-s-custom",
            "path": "/sys/users",
            "name": "sys:user:list",
            "component": "sys/User",
            "children": [
              {
                "id": 9,
                "title": "添加用户",
                "icon": null,
                "path": null,
                "name": "sys:user:save",
                "component": null,
                "children": []
              },
              {
                "id": 10,
                "title": "修改用户",
                "icon": null,
                "path": null,
                "name": "sys:user:update",
                "component": null,
                "children": []
              },
              {
                "id": 11,
                "title": "删除用户",
                "icon": null,
                "path": null,
                "name": "sys:user:delete",
                "component": null,
                "children": []
              },
              {
                "id": 12,
                "title": "分配角色",
                "icon": null,
                "path": null,
                "name": "sys:user:role",
                "component": null,
                "children": []
              },
              {
                "id": 13,
                "title": "重置密码",
                "icon": null,
                "path": null,
                "name": "sys:user:repass",
                "component": null,
                "children": []
              }
            ]
          },
          {
            "id": 3,
            "title": "角色管理",
            "icon": "el-icon-rank",
            "path": "/sys/roles",
            "name": "sys:role:list",
            "component": "sys/Role",
            "children": [
              {
                "id": 7,
                "title": "添加角色",
                "icon": "",
                "path": "",
                "name": "sys:role:save",
                "component": "",
                "children": []
              },
              {
                "id": 14,
                "title": "修改角色",
                "icon": null,
                "path": null,
                "name": "sys:role:update",
                "component": null,
                "children": []
              },
              {
                "id": 15,
                "title": "删除角色",
                "icon": null,
                "path": null,
                "name": "sys:role:delete",
                "component": null,
                "children": []
              },
              {
                "id": 16,
                "title": "分配权限",
                "icon": null,
                "path": null,
                "name": "sys:role:perm",
                "component": null,
                "children": []
              }
            ]
          },
          {
            "id": 4,
            "title": "菜单管理",
            "icon": "el-icon-menu",
            "path": "/sys/menus",
            "name": "sys:menu:list",
            "component": "sys/Menu",
            "children": [
              {
                "id": 17,
                "title": "添加菜单",
                "icon": null,
                "path": null,
                "name": "sys:menu:save",
                "component": null,
                "children": []
              },
              {
                "id": 18,
                "title": "修改菜单",
                "icon": null,
                "path": null,
                "name": "sys:menu:update",
                "component": null,
                "children": []
              },
              {
                "id": 19,
                "title": "删除菜单",
                "icon": null,
                "path": null,
                "name": "sys:menu:delete",
                "component": null,
                "children": []
              }
            ]
          }
        ]
      },
      {
        "id": 5,
        "title": "系统工具",
        "icon": "el-icon-s-tools",
        "path": "",
        "name": "sys:tools",
        "component": null,
        "children": [
          {
            "id": 6,
            "title": "数字字典",
            "icon": "el-icon-s-order",
            "path": "/sys/dicts",
            "name": "sys:dict:list",
            "component": "sys/Dict",
            "children": []
          }
        ]
      },
      {
        "id": 20,
        "title": "管理员",
        "icon": null,
        "path": null,
        "name": "sys:user",
        "component": "sys/Normal",
        "children": []
      }
    ],
    "authoritys": [
      "ROLE_admin",
      "ROLE_normal",
      "sys:manage",
      "sys:user:list",
      "sys:role:list",
      "sys:menu:list",
      "sys:tools",
      "sys:dict:list",
      "sys:role:save",
      "sys:user:save",
      "sys:user:update",
      "sys:user:delete",
      "sys:user:role",
      "sys:user:repass",
      "sys:role:update",
      "sys:role:delete",
      "sys:role:perm",
      "sys:menu:save",
      "sys:menu:update",
      "sys:menu:delete",
      "sys:user"
    ]
  }
}

以上文件复制可直接形成一个demo,视图文件自己定义一下放个template就行了

Logo

前往低代码交流专区

更多推荐