您的位置: 首页 >日志>前端技术>详细内容

前端技术

Vue动态路由主要场景

来源:本站原创 发布时间:2025-07-10 08:59:15 浏览次数: 【字体:

在 Vue 中实现动态路由主要有两种场景:基于用户权限动态生成路由表和基于路由参数动态渲染组件。下面我将分别介绍这两种场景的实现方法。

场景 1:基于用户权限动态生成路由表

这种场景适用于不同用户角色访问不同页面的情况。核心思路是:

  1. 用户登录后获取角色权限

  2. 根据权限过滤路由表

  3. 使用 router.addRoutes(Vue Router 3.x)或 router.addRoute(Vue Router 4.x)动态添加路由


步骤示例:

定义基础路由和异步路由

// router.js
import VueRouter from 'vue-router'

// 基础路由(所有用户都能访问)
export const constantRoutes = [
  { path: '/login', component: Login },
  { path: '/404', component: NotFound }
]

// 异步路由(需要权限控制)
export const asyncRoutes = [
  {
    path: '/admin',
    component: Layout,
    meta: { roles: ['admin'] },
    children: [{ path: 'dashboard', component: Dashboard }]
  },
  {
    path: '/user',
    component: Layout,
    meta: { roles: ['user', 'admin'] },
    children: [{ path: 'profile', component: Profile }]
  }
]

const router = new VueRouter({
  routes: constantRoutes
})

export default router

权限校验与动态添加路由

// permission.js(路由守卫)
import router from './router'
import { asyncRoutes } from './router'

router.beforeEach(async (to, from, next) => {
  const hasToken = localStorage.getItem('token')
  if (hasToken) {
    if (to.path === '/login') {
      next('/')
    } else {
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          // 获取用户角色
          const { roles } = await store.dispatch('user/getInfo')
          // 根据角色过滤路由
          const accessRoutes = filterAsyncRoutes(asyncRoutes, roles)
          // 动态添加路由
          accessRoutes.forEach(route => {
            router.addRoute(route)
          })
          // 确保路由添加完成
          next({ ...to, replace: true })
        } catch (error) {
          next('/login')
        }
      }
    }
  } else {
    next('/login')
  }
})

// 过滤路由的工具函数
function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp.meta?.roles)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })
  return res
}

function hasPermission(roles, routeRoles) {
  if (!routeRoles) return true
  return roles.some(role => routeRoles.includes(role))
}


场景 2:基于路由参数动态渲染组件

这种场景适用于同一个路由路径根据不同参数渲染不同内容的情况。核心思路是:

  1. 使用路由参数(如 :id)标识不同内容

  2. 在组件内通过 $route.params 获取参数并动态加载数据

步骤示例:

定义动态路由

// router.js
{
  path: '/article/:id',
  name: 'Article',
  component: Article
}


在组件内根据参数加载数据

<!-- Article.vue -->
<template>
  <div>
    <h1>{{ article.title }}</h1>
    <p>{{ article.content }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      article: {}
    }
  },
  created() {
    this.fetchArticle()
  },
  watch: {
    // 监听路由参数变化,避免相同组件实例复用导致数据不更新
    '$route.params.id': {
      immediate: true,
      handler() {
        this.fetchArticle()
      }
    }
  },
  methods: {
    async fetchArticle() {
      try {
        const res = await axios.get(`/api/articles/${this.$route.params.id}`)
        this.article = res.data
      } catch (error) {
        console.error(error)
      }
    }
  }
}
</script>

注意事项

  1. Vue Router 4.x 变化

    1. Vue Router 4.x(Vue 3 配套)中,router.addRoutes 已被弃用,需使用 router.addRoute 逐个添加路由。

    2. 动态添加路由后,需通过 next({ ...to, replace: true }) 确保路由更新。

  2. 路由守卫的位置

    1. 动态路由的权限校验通常放在全局前置守卫(beforeEach)中。

  3. 404 页面处理

    1. 确保 404 路由在动态路由之后添加,避免拦截正常路由。


×

用户登录