使用vue3+TS实现动态路由【2023无套路不需要VIP】

之前把注入路由写在beforeEach里面,在搭建动态路由前出现了很多问题,尝试各种方法都不行,心都累了。网上基本上都是这样方式,不能这样搞,反正我的项目是实现不了的。
不知道出现多少错误,比如,无法找到文件、import引入错误。

Uncaught (in promise) Error: Cannot find module './() => webpack_require("./src/views lazy recursive ^) /.* " ) (   . / ")(~./ ")( ./(templode.component]~)
部分错误代码如下:
使用vue3+TS实现动态路由【2023无套路不需要VIP】_第1张图片
使用vue3+TS实现动态路由【2023无套路不需要VIP】_第2张图片

请添加图片描述
几经磨砺,用了很多方法,搞了好几次。最后换了一种写法,才弄出来。

vue/cli版本如下,基本上是目前最新版本。

    "@typescript-eslint/eslint-plugin": "^5.4.0",
    "@typescript-eslint/parser": "^5.4.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-typescript": "~5.0.0",
    "@vue/cli-service": "~5.0.0",

真正能实现的代码,正确代码,如下!!!!!!!!!!!!!!!
实现:两个文件代码menu.tsrouter/index.ts
1. menu.ts

export const menuData: any = [
  {

    id: 11,

    parent_id: 1,

    name: 'about',

    path: '/about',

    component: 'About.vue',

    meta: { title: '关于我们', type: 'type_menu', redirect_path: '' }

  },

  {

    id: 12,

    parent_id: 1,

    name: 'form',

    path: '/form',

    component: 'form/index.vue',

    meta: { title: '主页', type: 'type_menu', redirect_path: '' },

    children: [

      {

        id: 13,

        parent_id: 12,

        name: 'child',

        path: '/child',

        component: 'form/child/index.vue',

        meta: { title: '日历', type: 'type_menu', redirect_path: '' }

      }

    ]

  }

]

2. router/index.ts代码如下
方式一:有登录,在beforeEach中注入路由。
菜单都扁平化了,测试中菜单有children就会报错,把children全部去掉了。
关键点:在beforeEach中注入路由后,一定要next(to.fullPath)
使用vue3+TS实现动态路由【2023无套路不需要VIP】_第3张图片

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Layout from '@/layout/index.vue'
import { cookie, storage } from '@/utils/tool'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'Layout',
    component: Layout,
    redirect: '/workBench',
    children: [
      {
        path: '/workBench',
        name: 'workBench',
        component: () => import(/* webpackChunkName: "workBench" */ '../views/workBench/index.vue')
      }
    ]
  },
  {
    path: '/login',
    name: 'login',
    component: () => import(/* webpackChunkName: "login" */ '@/views/login/index.vue')
  },
  {
    path: '/:pathMatch(.*)*',
    component: () => import(/* webpackChunkName: "404" */ '@/layout/other/404.vue')
  }
]

// 菜单扁平化
const flattenMenu = (menu: any) => {
  let result: any = []
  for (let i = 0; i < menu.length; i++) {
    const data = {
      name: menu[i].name,
      path: menu[i].path,
      component: () => import(`@/views/${menu[i].component}`)
    }
    result.push(data)
    if (Array.isArray(menu[i].children)) {
      result = result.concat(flattenMenu(menu[i].children))
    }
  }
  return result
}

const router = createRouter({
  history: createWebHistory(),
  routes
})

let isFlag = false
const token = cookie.get('TOKEN')
router.beforeEach(async (to, from, next) => {
  if (to.path === '/login') {
    cookie.remove('TOKEN')
    storage.removeItem('MENU')
    next()
    return
  }
  if (token) {
    if (!isFlag) {
      isFlag = true
      const menuData: any = storage.getItem('MENU') || []
      const menuList = flattenMenu(menuData)
      menuList.forEach((element: any) => {
        router.addRoute('Layout', element)
      })
      next(to.fullPath)
    } else {
      next()
    }
  } else {
    next({ path: '/login' })
  }
})

export default router

方式二:无登录

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { menuData } from './menu'
import Layout from '@/layout/index.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'Layout',
    component: Layout,
    redirect: '/workBench',
    children: [
      {
        path: '/workBench',
        name: 'workBench',
        component: () => import(/* webpackChunkName: "workBench" */ '../views/workBench/index.vue')
      }
    ]
  },
  {
    path: '/login',
    name: 'login',
    component: () => import(/* webpackChunkName: "login" */ '@/views/login/index.vue')
  },
  {
    path: '/:pathMatch(.*)*',
    component: () => import(/* webpackChunkName: "404" */ '@/layout/other/404.vue')
  }
]
// childType是我项目需要判断菜单为一级添加layout布局
function addRoutes (routes: RouteRecordRaw[], menu: any[], childType?: string) {
  for (const item of menu) {
    let route: any = {}
    if (childType) {
      route = {
        path: item.path,
        name: item.name,
        component: () => import(`@/views/${item.component}`),
        meta: item.meta
      }
    } else {
      route = {
        path: item.path,
        name: item.name,
        component: Layout,
        meta: item.meta,
        children: [
          {
            path: '',
            component: () => import(`@/views/${item.component}`)
          }
        ]
      }
    }
    if (item.children) {
      route.children = []
      addRoutes(route.children, item.children, 'child')
    }
    routes.push(route)
  }
}

// 注入路由
addRoutes(routes, menuData)

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

End~~~~~~~

你可能感兴趣的:(vue.js,前端,javascript,typescript)