You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于VueJS Router Guards实现访问控制及路由加载范围限制

Enforce Route Loading Context with Vue Router Guards

Got it, let's break down how to implement this access control exactly as you need it. The goal is to make sure main routes only load in App.vue's <router-view>, and nested routes only load in their parent component's <router-view>. Here's a step-by-step solution:

1. Mark Routes with Meta Information

First, add metadata to your routes to define where they're allowed to load. We'll use a allowedParent field in the meta object:

  • For main routes (those meant for App.vue), set allowedParent: null (since they have no parent route).
  • For nested routes, set allowedParent to the name of their parent route (so we can verify they're loading under the correct parent).
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import HomeProfile from '../views/HomeProfile.vue'
import About from '../views/About.vue'
import AboutTeam from '../views/AboutTeam.vue'

const routes = [
  // Main routes (only for App.vue's router-view)
  {
    path: '/home',
    name: 'Home',
    component: Home,
    meta: { allowedParent: null },
    // Nested routes (only for Home.vue's router-view)
    children: [
      {
        path: 'profile',
        name: 'HomeProfile',
        component: HomeProfile,
        meta: { allowedParent: 'Home' }
      }
    ]
  },
  {
    path: '/about',
    name: 'About',
    component: About,
    meta: { allowedParent: null },
    // Nested routes (only for About.vue's router-view)
    children: [
      {
        path: 'team',
        name: 'AboutTeam',
        component: AboutTeam,
        meta: { allowedParent: 'About' }
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

2. Global Route Guard for Top-Level Checks

Add a global beforeEach guard to validate that every route is loading under its allowed parent. This catches cases where someone might try to navigate directly to a nested route without its parent, or misconfigure routes.

router.beforeEach((to, from, next) => {
  // Get the actual parent route (from the matched route hierarchy)
  const actualParentRoute = to.matched.length > 1 
    ? to.matched[to.matched.length - 2].name 
    : null

  // Compare actual parent with allowed parent
  if (to.meta.allowedParent !== actualParentRoute) {
    const errorMsg = to.meta.allowedParent 
      ? `Route "${to.name}" can only load under parent route "${to.meta.allowedParent}"`
      : `Route "${to.name}" can only load in App.vue's root router-view`
    
    console.error(errorMsg)
    // Redirect to a safe route (e.g., home) instead of allowing invalid navigation
    next({ name: 'Home' })
    return
  }

  // All checks passed, proceed with navigation
  next()
})

3. Component-Level Guards for Extra Safety

To prevent edge cases (like loading a nested route in a different parent component's <router-view> via programmatic navigation), add guards directly to components that contain a <router-view>.

For example, in Home.vue:

<template>
  <div class="home">
    <h1>Home Page</h1>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'Home',
  beforeRouteUpdate(to, from, next) {
    // Verify the incoming route is a child of Home and allowed here
    const isHomeChild = to.meta.allowedParent === 'Home'
    const isUnderHome = to.matched.some(route => route.name === 'Home')

    if (!isHomeChild || !isUnderHome) {
      console.error('This route can only load in Home.vue\'s router-view')
      next(false) // Block navigation
      return
    }

    next()
  }
}
</script>

Repeat this pattern in About.vue (or any other component with a <router-view>):

<template>
  <div class="about">
    <h1>About Page</h1>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'About',
  beforeRouteUpdate(to, from, next) {
    const isAboutChild = to.meta.allowedParent === 'About'
    const isUnderAbout = to.matched.some(route => route.name === 'About')

    if (!isAboutChild || !isUnderAbout) {
      console.error('This route can only load in About.vue\'s router-view')
      next(false)
      return
    }

    next()
  }
}
</script>

How This Works

  • Global Guard: Checks the route hierarchy to ensure every route is nested under its allowed parent. This prevents invalid route configurations or direct URL manipulation.
  • Component Guards: Adds an extra layer of safety to ensure that even if someone tries to load a route in the wrong component's <router-view> (via $router.push or other methods), the navigation is blocked.

This setup fully enforces your requirement: main routes stay in App.vue's router-view, and nested routes only load in their parent component's router-view.

内容的提问来源于stack exchange,提问作者margherita pizza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:33:21