Vue动态路由

Vue Router动态路由思路

一、路由存储方式

以下内容仅作为参考,如有错误内容还请指出

  • 数据库存储
    在数据库中新建路由表,发起用户登录请求由后端判断当前用户权限(管理员、普通用户)决定返回的data数据,其中数据中包含用户基本信息以及对应路由。
  • 前端存储
    正常填写路由数据,但需要在路由下标注该路由权限,发起用户登录后根据返回结果中的用户权限过滤路由信息。

二、数据处理

响应数据中data.router(路由树)应声明对应的store并做持久化存储,防止刷新后关闭网页后丢失菜单信息(根据个人需要,若token没有失效用户重新进入网页不需要登录,则应持久化处理后的菜单信息,方便回显)

// router格式
{
	path:'',   // router.push()对应路径
	name:'',   // 名称跳转(唯一标识)
	// 不要在meta外添加自定义属性,因为在addRoute时自定义属性不会被识别
	meta:{     // 元信息,可以添加自定义属性
		title:'标题',
		fullPath:'', // 跳转全路径,根据情况看后端处理还是前端处理
	}
	component:undefined,
	children:[]
}

1. push跳转

在路由push跳转时,若路径以/开头则会被认为是顶级路由,router会从首层路由向下寻找,若不以/开头则替换当前路由的兄弟路由,如

/**
  * login
  * layout
  *     first
  *     second
  *     third
  */

假设当前处于/layout/first下,执行router.push(‘second’)会跳转至/layout/second下,但若执行router.push(‘/second’),router会寻找/second路由。因此在处理router时应存储跳转当前路由的全路径也就是fullPath会更为方便

2.路由添加方式

刚开始写demo时遇到了很多问题,这里做一下分享以及相关错误解释

  • 创建router时将路由分为dynamicRouter与staticRouter两个对象,展开放入createRouter的routes下,在后续拿到处理好的路由时,遍历push到dynamicRouter的children数组上,由于push时修改的初始对象,理应能够将每一项都放在动态路由的子路由上,但实际上没有任何效果。
    大概是因为导入的router对象在main.js中执行app.use(router)时children属性是空数组,而在登录后即使向该数组添加值,也不会被路由识别
  • 在通过addRoute添加路由时,若被添加的路由path以/开头,即使addRoute使用了name参数该路由依旧会被当做顶级路由处理,而非作为name的子路由,因此children的path不要以/开头

3.component引入

// 在vite中提供了import.meta.glob(path)的方式引入component组件,path不能使用模板字符串
const modules = import.meta.glob('/src/views/**/*.vue')

import.meta.glob是vite提供的批量导入文件的方式,其中**代表匹配包含/在内的任意字符串.*代表不含/的任意字符串,因此上述函数会将view下所有的vue文件全部引入到modules,其返回值为map形式,可以直接使用modules[]路径导入文件

三、代码

1.后端返回数据

[
    {
      path: 'user',
      name: 'user',
      meta: {
        title: '用户',
      },
      children: [
        {
          // 认为从父级到子级path的拼接最终组件的访问push路径
          path: 'userInfo',
          name: 'userInfo',
          meta: {
            title: '用户信息',
          },
        },
        {
          path: 'userAvatar',
          name: 'userAvatar',
          meta: {
            title: '用户头像',
          },
        },
      ],
    },
    {
      path: 'count',
      name: 'count',
      meta: {
        title: '账号',
      },
      children: [
        {
          // 认为从父级到子级path的拼接最终组件的访问push路径
          path: 'password',
          name: 'password',
          meta: {
            title: '密码',
          },
        },
      ],
    },
  ],

2.数据处理

// 该router对象必须是在main.js中use的router对象
import router from './index.js'
// 处理时不对数据做校验,如有借鉴请自行添加其余数据处理预防出错
const generateDynamicRouter = (data) => {
	const result = generateRouter('/',data)
	for(const route of result) {
	   router.addRoute('layout',route)
	}
}
/**
  *  递归函数,传入访问公共前缀与router数组,期待返回值为router数组
  */
const generateRouter = (path,router) =>  {
	let result = []
	for(const child of router){
		// 拿到child后,需要判断其是否为叶子节点,如果有children且长度大于0为非叶子节点
		let leaf = !(child.children && child.children.length > 0)
		result.push({
			path:child.path,  // path不能带/,否则会被当做顶级路由处理,自行处理
			name:child.name,  // 唯一标识
			meta:{
				title:child.meta.title, // 标题,可以在el-menu中遍历作为标题
				/** 
				  * 只有叶子节点才能有path,且动态路由后续会放在顶级路由layout下的children属性上,因此会加上/layout
				  * 后续拼接的内容为外部传入的父级path + 当前路由的path
				  * 初始path为/,递归时会使用传入path + item.path + '/',保证递归过程中可以直接拼接item.path
				  */
				fullPath:leaf ? '/layout' + path + item.path : ''
			}
			// 自带/,因此views后不加/
			component:leaf ? modules[`/src/views${path+child.path}/index.vue`] : undefined,
			children: leaf ? [] : generateRouter(path + child.path + '/',child.children)
		})
	}
	// 遍历结束后会将该路由数据返回,当到达叶子节点后就会直接push,非叶子节点递归处理后将其返回值赋值给children后push
	return rusult
}

3.后续处理

动态路由的目的本质上是为了实现根据权限控制看到的内容不同,因此看到的首页也会不同,因此在添加完路由后需要找到第一个叶子节点作为首页

// 叶子节点是非常好找的,在刚处理好的动态路由中meta信息存储每个节点的全路径,且非叶子节点的children非空
const getFirstMenu = (routers) => {
 // 数组的第一个路由的chilren有值,则继续传入,为null则返回该路由的meta.fullPath
 return routers[0].chilren ? getFirstMenu(routers[0].children) :routers[0].meta.fullPath
}

分享就到这,如果后续有问题欢迎交流

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值