Vue3+Vite实现动态路由的详细实例代码

项目基本目录

1.首先定义初始默认的路由routes(router.js文件),vue文件使用import引入可以按需加载

import {
    createRouter,
    createWebHashHistory
} from "vue-router";

import store from '../store/index.js'

const routes = [{
        path: "/login",
        component: () => import("../view/Login/index.vue"),

        children: [],
        meta: {
            title: '登录页',
            hideMenu: true, //加入hideMenu属性,不展示在侧边栏
        },
        name: "Login",
    },
    {
        path: "/",
        component: () => import("../view/Home/index.vue"),
        meta: {
            keepalive: true,
            title: "主页",
        },
        name: 'Home',
        // hideMenu: true,//不展示在侧边栏
        children: [],
        redirect: '/index'
    },
]

2.在store的login.js模块写入调用后端数据的函数(写在vuex的action对象中,方便全局异步调用)

Vuex 允许我们将 store 分割成模块(module),比如登录模块,项目各个业务不相关的模块。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块(具体可以看主页另一篇博客)

3.执行addRoutes函数获取动态路由 (在router.js文件,点击登录成功后,在全局路由守卫去判断是否登录成功,再调用addRoutes函数)

(1)全局路由守卫逻辑具体可看注释,好处是进入项目之后,刷新页面路由守卫会拦截跳转,可以重新执行addRoutes()获取路由,先获取动态路由,再执行跳转,不然页面会报本地路由找不到(一个小坑)

(代码如下)

router.beforeEach(async (to, from, next) => { //路由守卫
    if (store.state.login.token) { //存在token
        if (to.path == '/login') { //存在token,如果想跳转到登录页,默认有token跳转进项目首页
            next({
                path: '/'
            })
        } else {
                //如果存在token,跳转进项目页面,则判断当前后端返回的路由有无长度
                //或者有无即将跳转路由的name
            if (store.getters['login/getRoutes'].length || to.name != null) {
                next() //有的话直接跳转
            } else { //不满足条件的话,重新请求后端动态路由数据
                await addRoutes(); //addRoutes()必须加入await!!!!等待逻辑执行完毕获取路由
                // 如果 addRoute 未完成,路由守卫会一层一层的执行执行,不加next()可能导致卡死!
                //直到 addRoute 完成,找到对应的路由
                next({
                    ...to,
                    replace: true
                })
            }
        }
    } else {
        if (to.path == '/login') {
            next()
        } else {
            next('/login')
        }
    }
})

后端返回的格式

(2)(重点在这,前面的步骤都可以不是重点)Vite使用import.meta.glob动态导入view文件夹所有前端页面,并调用addRoutes()函数执行获取动态路由数据并做处理(代码如下),主要作用是替换掉后端返回的component格式,再addRoute进路由表(看不懂的可以看代码注释或者可以搬进自己的项目打印看看每一步获取的数据)

let asyncRoutes = [] //定义数组接收后端返回的路由

const routeAllPathToCompMap =import.meta.glob(`../view/**/*.vue`);
//**为通配符,vite不支持require导入方式,故用import.meta.glob(vite动态导入)
/*import.meta.glob
 * 该方法匹配到的文件默认是懒加载,通过动态导入实现,构建时会分离独立的 chunk,是异步导入,返回的是 Promise
 * /*import.meta.globEager
 * 该方法是直接导入所有模块,并且是同步导入,返回结果直接通过 for...in循环就可以操作
 */
async function addRoutes() {
    await store.dispatch('login/getNewRoutes').then((res) => { //获取后端返回的动态路由
        if (res.data && res.data.length) {
            // let homeRouteChildren = [];
            asyncRoutes = res.data;
            /*
             * 1。拿到处理完毕home的children,最终替换掉原来的children,给菜单渲染提供支持
             * 2.通过递归,调用router.addRoute,把每一项route插到对应的父route下
             */
            //服务端配置了路由,但前端还没添加对应文件的路由列表,内容是路由的component值(服务端的)
            // const unForList = ['']
            const homeChildren = routes[1].children;
            const dfs = (parentRouteName = 'Home', asyncRoutes = [], originRouteChildren = []) => {
                if (!Array.isArray(asyncRoutes)) return [];
                asyncRoutes.forEach(route => {
                    // if (unForList.includes(route.component)) return;
/**后端返回来的路由component是字符串,如component: "view/Index/index.vue",
 * 前端需要把component: "view/Index/index.vue" 转化为组件对象
 * component:() => import("/src/view/Index/index.vue")
**/
                    route.component = routeAllPathToCompMap[`../${route.component}`];
                    // route.component = () => import(`../${route.component}`);
                    const routeChildren = route.children;

                    router.addRoute(parentRouteName, route);

                    route.children = dfs(route.name, routeChildren)

                    originRouteChildren.push(route)
                })
                return originRouteChildren
            }
            // homeRouteChildren = dfs(asyncRoutes)
            dfs('Home', asyncRoutes, homeChildren)
        }
    });
}

最终转化完成,路由数据格式如下

动态路由到此完成

总结

到此这篇关于Vue3+Vite实现动态路由的文章就介绍到这了,更多相关Vue3+Vite动态路由内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue3+vite自定义封装vue组件发布到npm包的全过程

    目录 创建项目 创建组件 导出组件 使用vite构建 打包 注册->登录npm 发布前准备 发布到npm 参考: 总结 创建项目 “vue”: “^3.2.8” “vite”: “^2.5.2” 习惯用HB的直接用创建vue3项目即可 或 npm init vite@latest 创建组件 打开项目 在src/components文件夹下新增文件,我这里叫TestBtn.vue <template> <button>我是测试要发布的按钮组件</button> &l

  • vue3+vite引入插件unplugin-auto-import的方法

    自动引入 composition api,不需要再手动引入.github地址:https://github.com/antfu/unplugin-auto-import 下载 npm i unplugin-auto-import -D 修改vite.config.ts文件 import AutoImport from 'unplugin-auto-import/vite' export default defineConfig({ plugins: [vue(),AutoImport({ imp

  • vue3 Vite 进阶rollup命令行使用详解

    目录 rollup介绍 以命令行方式打包 Tree Shaking Rollup 的命令行使用 命令行 format 格式 rollup.config.js 设置/获取环境变量 插件 plugins rollup介绍 开源类库优先选择 以 ESM 标准为目标的构建工具 Tree Shaking 以命令行方式打包 安装 rollup npm install -g rollup 创建 index.js 文件 import path from "path"; console.log(&quo

  • vue3+vite中使用import.meta.glob的操作代码

    目录 前言: vue3中使用 import.meta.glob 具体方法: 前言: 在vue2的时候,我们一般引入多个js或者其他文件,一般使用  require.context 来引入多个不同的文件,但是vite中是不支持 require的,他推出了一个类似的功能,就是用import.meta.glob来引入多个,单个的文件. 这里说说他们的对比和区别: vue2 中使用  require 来引入多个不同的js文件 1.引入  modules 下的所有的js文件 const modulesFi

  • Vue3+Vite实现动态路由的详细实例代码

    项目基本目录 1.首先定义初始默认的路由routes(router.js文件),vue文件使用import引入可以按需加载 import { createRouter, createWebHashHistory } from "vue-router"; import store from '../store/index.js' const routes = [{ path: "/login", component: () => import("../

  • 如何利用Vue3管理系统实现动态路由和动态侧边菜单栏

    目录 前言 动态路由 动态侧边菜单栏 总结 前言 在做Vue管理系统的时候,都会遇到的一个需求:每个用户的权限是不一样的,那么他可以访问的页面(路由),可以操作的菜单选项是不一样的,如果由后端控制,我们前端需要去实现动态路由,动态渲染侧边菜单栏. 动态路由 在本示例管理系统中,由于每个用户的权限不一样,拥有的可以访问的路由页面也不一样,用户能访问的路由页面都是后端根据权限动态配置的 我们前端需要根据后端接口返回的路由表去动态增删路由,从而生成这个用户所拥有的路由. 重点:实现动态路由api ro

  • Struts2实现生成动态验证码并验证实例代码

     一.基本流程: 产生一个验证码页面(很小)→嵌入到表单中→点击可以刷新页面→表单提交时验证. 二.方法: 1.定义TestAction,实现画图方法 package com.zhuguang.action; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.util.Map; import javax.se

  • jQuery动态增减行的实例代码解析(推荐)

    先给大家展示下效果图: 这是没有增加时的界面: 增加后的界面: 删除后的界面: 原因分析: 不擅长jquery和JavaScript 场景: 代码如下: <table class="table table-bordered"> <thead> <tr> <th style="width: 10px">輪次</th> <th style="width: 100%">比賽時間&l

  • Android 动态添加Fragment的实例代码

    1.fragment1布局及代码 布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width=&quo

  • PyQt5主窗口动态加载Widget实例代码

    本文研究的主要是PyQt5主窗口动态加载Widget的代码示例,具体如下. 我们通过Qt Designer设计两个窗口,命名为主窗口(MainForm)和子窗口(ChildrenForm).我们在主窗口的空白中央添加一个栅格布局并命名为MaingridLayout,等会需要将ChildrenForm放进去. 编写代码 from PyQt5 import QtWidgets from MainForm import Ui_MainForm from Children import Ui_Form

  • 使用 Node.js 实现图片的动态裁切及算法实例代码详解

    背景&概览 目前常见的图床服务都会有图片动态裁切的功能,主要的应用场景用以为各种终端和业务形态输出合适尺寸的图片. 一张动辄以 MB 为计量单位的原始大图,通常不会只设置一下显示尺寸就直接输出到终端中,因为体积太大加载体验会很差,除了影响加载速度还会增加终端设备的内存占用.所以要想在各种终端下都能保证图片质量的同时又确保输出合适的尺寸,那么此时就需要根据图片 URL 来对原始图片进行裁切,然后动态生成并输出一张新的图片. URL 的设计 图片 URL 需要包含图片 id.尺寸.质量等信息.有两种

  • django js 实现表格动态标序号的实例代码

    django js 实现表格动态标序号 <table class="table table-striped"> <thead> <tr class="key_words_head"> <th>序号</th> <th>类目</th> <th>关键词</th> <th>操作</th> </tr> </thead> &

  • MyBatis动态创建表的实例代码

    项目中业务需求的不同,有时候我们需要动态操作数据表(如:动态建表.操作表字段等).常见的我们会把日志.设备实时位置信息等存入数据表,并且以一定时间段生成一个表来存储,log_201806.log_201807等.在这里我们用MyBatis实现,会用到动态SQL. 动态SQL是Mybatis的强大特性之一,MyBatis在对sql语句进行预编译之前,会对sql进行动态解析,解析为一个BoundSql对象,也是在此对动态sql进行处理. 在动态sql解析过程中,#{ }与${ }的效果是不一样的:

  • python:动态路由的Flask程序代码

    如下所示: # Copyright (c)2018, 东北大学软件学院学生 # All rightsreserved # 文件名称:a.py # 作 者:孔云 #问题描述: from flask import Flask app=Flask(__name__) @app.route('/') def index(): return '<h1>Flask Web程序开始了....<h1>' @app.route('/user/<name>') def user(name)

随机推荐