Vite + Vue3 动态路由 - 踩坑记录

Vue
569
0
0
2022-10-25

常见的几个问题

  • 刷新页面空白
  • addRoute 没有加载完成就访问 -> next() 改成 next({…to, replace: true})
  • 路由重名, 检查路由的name是否有重复
  • 路由守卫死循环
  • 添加一些条件, 比如: 判断是否已经获取到了路由数据
  • 刷新页面会跳转到404页面
  • 在动态路由添加完成后, 再添加404的路由
  • Vite 的组件懒加载
const viteComponent = import.meta.glob("../views/**/*.vue")
// ...
component: viteComponent[`../views${item.path}.vue`]


贴一下路由守卫部分的代码

// 路由守卫
router.beforeEach((to, from, next) => {
    //在跳转路由之前,先清除所有的请求 
    clearPending()

    // 判断是否登录 
    if (to.path === "/login") {
        next()
    } else {
        let token = getToken()
        if (token && typeof token != "undefined") {
            // 如果vuex中没有路由数据,则获取路由数据 
            if (store.state.menus.length === 0) {
                // 异步 确保路由已经添加完成 (貌似不需要) 
                getRouters().then(() => {
                    next({
                        ...to, // 无限访问目标路由, 直到 addRoute() 添加完成 
                        replace: true, // 本次操作后,不能通过浏览器后退按钮,返回前一个路由
                    })
                })
            } else {
                next()
            }
        } else {
            next("/login")
        }
    }
})

// 获取路由数据
const getRouters = () => {
    return new Promise((resolve) => {
        // 请求路由数据
        systemMenu.list().then((res) => {
            // 存入vuex
            store.dispatch("initMenu", res.data).then(() => {
                // 处理路由数据 
                let data = handlerRouterDate(res.data)
                // 添加路由
                data.forEach((item: any) => {
                    router.addRoute("base", item)
                })

                // 在动态路由添加完成后, 才添加 404路由 否则会跳转到404页面
                router.addRoute("base", {
                    path: "/:w+",
                    name: "404Page",
                    component: () => import("@/views/404.vue"),
                })

                // 返回成功 
                resolve(null)
            })
        })
    })
}

// 处理路由数据
const handlerRouterDate = (data: any) => {
    let routerData = <any>[]

    // 遍历路由数据
    data.forEach((item: any) => {
        if (item.children) {
            // 递归处理子路由 
            let temp = handlerRouterDate(item.children)
            // 处理完成后,添加到同一级返回
            temp.forEach((sub: any) => {
                if (sub.router != "-") {
                    routerData.push(sub)
                }
            })
        }

        if (item.router != "-") {
            // 处理路由数据格式
            routerData.push(handlerRouterItem(item))
        }
    })

    return routerData
}

// 处理单个路由数据
const handlerRouterItem = (item: any) => {
    return {
        path: item.router,
        name: item.name,
        // webpack 用以下方式引入 
        // component: () => import(`@/views${item.path}.vue`) 
        // vite 需要以下方式引入 
        component: viteComponent[`../views${item.path}.vue`],
    }
}