Vue Router 4 动态添加路由详解

2024-11-24 11:06:56

服务端的数据

思考一下,前端在实现动态菜单的时候,服务端会返回什么样的数据?

创建一个菜单的时候,最基本的是不是得有一个id、标题、路由、组件、父菜单,至于可访问的权限,暂不考虑。

假设服务端给前端返回了一个树形结构的数据(其实大多数时候,服务端都是把数据一股脑丢给前端处理的,这里为了方便说明问题,处理成树形结构)

// 服务端返回的数据
// 一般这个数据是存放在store中
const menus = [
  {
  	id: 0,
    pid: 0,
    name: '',
    title: '初始化',
    path: '',
    component: '',
    children: [{
  		id: 2,
    	pid: 0,
    	title: '安装与配置',
    	name: 'home.install',
    	path: 'install',
    	component: 'views/install/Install'
  	}]
  }, {
   	id: 1,
    pid: 0,
    title: '基础知识',
    name: '',
    path: '',
    component: '',
    children: [{
    	id: 3,
      pid: 1,
      title: '路由嵌套',
      name: 'home.nesting',
      path: 'nesting',
      component: 'views/nesting/Nesting'
    }]
  }
]


menus生成的菜单


服务端数据转路由记录

需要将服务端返回的数据转成标准路由地址

/**
  * 将菜单数据转化成路由记录
  * @param data 菜单数据
  * @param parent 
  * @return 路由记录数组
  **/
function transRoute(data) {
  // 路由记录数组
  const routes = []
	data.forEach(v => {
    
    // 判断路由地址是否存在
    if(v.path !== '') {
      // vite下动态加载组件方式
      const modules = import.meta.glob('../views/**/*.vue')
      
      // 路由记录对象
      const route = {}
      route.name = v.name
    	route.path = v.path
      // 这里会被解析成() => import('/src/views/xx/xx.vue')
      route.component = modules[`../${v.component}.vue`]
      routes.push(route)
    }
    
    // 如果菜单数据存在子节点children
  	if(v.children && v.children.length) {
    	transRoute(v.children)
    }
  })
  return routes
}

转化完成的数据


将路由记录数据动态挂载到router实例

/**
 * 动态添加路由
 * @param routes 路由记录数组
 * @param router router实例
 **/
export const addRouteDynamically = (routes, router) => {
  // 获取已挂载的routes路由记录,
  // 找到对应的静态路由,
  // 将对应的子路由动态添加到该静态路由
  // 最后挂载到router实例
  const _routes = router.options.routes
  _routes[1].children = [
    ..._routes[1].children, 
    ...routes
  ]
  router.addRoute(_routes[1])
}


动态添加完成的数据

解决浏览器刷新导致动态路由消失的问题

思路是,判断当前路由(to对应的路由地址)是否存在,不存在,则重新添加

解决浏览器刷新导致动态路由消失的问题

相关推荐