Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 动态路由与路由守卫

动态路由与路由守卫

Vue Router 4 的动态路由和路由守卫是构建复杂应用的关键特性。动态路由允许根据参数或条件动态加载页面,而路由守卫则提供导航控制,用于权限验证、数据预加载等场景。本节将深入讲解这两者的实现方式、使用方法和应用场景,并通过示例展示如何在 Vue 3 项目中应用它们。

动态路由

动态路由通过路径参数或查询参数实现灵活的页面渲染,适用于需要根据用户输入或数据动态显示内容的场景。

基本用法

定义动态路由

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', name: 'Home', component: () => import('@/views/Home.vue') },
  { 
    path: '/product/:id', 
    name: 'Product', 
    component: () => import('@/views/Product.vue') 
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

使用参数

<!-- src/views/Product.vue -->
<template>
  <div>
    <h1>产品 ID: {{ productId }}</h1>
    <p>产品名称: {{ productName }}</p>
    <button @click="goBack">返回</button>
  </div>
</template>

<script>
import { useRoute, useRouter } from 'vue-router';
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const route = useRoute();
    const router = useRouter();
    const productId = ref(route.params.id);
    const productName = ref('');

    // 模拟数据加载
    onMounted(() => {
      const products = {
        '1': '苹果',
        '2': '香蕉',
        '3': '橙子'
      };
      productName.value = products[productId.value] || '未知产品';
    });

    const goBack = () => router.go(-1);

    return { productId, productName, goBack };
  }
};
</script>
  • 效果:访问 /product/1 显示“产品 ID: 1”和“产品名称: 苹果”。

动态导航

<!-- src/App.vue -->
<template>
  <div>
    <router-link to="/">首页</router-link>
    <router-link :to="{ name: 'Product', params: { id: 2 } }">产品 2</router-link>
    <router-view />
  </div>
</template>

多参数与可选参数

支持多个动态参数和可选参数:

const routes = [
  { 
    path: '/user/:userId/post/:postId?', // postId 可选
    name: 'UserPost', 
    component: () => import('@/views/UserPost.vue') 
  }
];
<!-- src/views/UserPost.vue -->
<template>
  <div>
    <h1>用户: {{ userId }}</h1>
    <p>帖子: {{ postId || '未指定' }}</p>
  </div>
</template>

<script>
import { useRoute } from 'vue-router';
import { ref } from 'vue';

export default {
  setup() {
    const route = useRoute();
    const userId = ref(route.params.userId);
    const postId = ref(route.params.postId);
    return { userId, postId };
  }
};
</script>
  • 访问:
    • /user/123 显示“用户: 123”和“帖子: 未指定”。
    • /user/123/post/456 显示“用户: 123”和“帖子: 456”。

通配符路由

捕获所有未匹配路径:

const routes = [
  { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/NotFound.vue') }
];
<!-- src/views/NotFound.vue -->
<template>
  <h1>404 - 页面未找到</h1>
</template>
  • 效果:访问 /random/path 显示 404 页面。

路由守卫

路由守卫用于控制导航行为,可在全局、路由级别或组件内实现。

1. 全局守卫

前置守卫(beforeEach)

// src/router/index.js
router.beforeEach((to, from, next) => {
  console.log(`从 ${from.path} 到 ${to.path}`);
  if (to.meta.requiresAuth && !isAuthenticated()) {
    next('/login'); // 未登录跳转
  } else {
    next(); // 放行
  }
});

function isAuthenticated() {
  return !!localStorage.getItem('token'); // 模拟认证
}
  • 配置:
    const routes = [
      { path: '/admin', meta: { requiresAuth: true }, component: () => import('@/views/Admin.vue') },
      { path: '/login', component: () => import('@/views/Login.vue') }
    ];
    
  • 效果:访问 /admin 时,未登录跳转到 /login。

后置守卫(afterEach)

router.afterEach((to, from) => {
  console.log(`导航到 ${to.path} 完成`);
});

2. 路由独享守卫

在特定路由上定义:

const routes = [
  {
    path: '/admin',
    component: () => import('@/views/Admin.vue'),
    beforeEnter: (to, from, next) => {
      if (isAuthenticated()) next();
      else next('/login');
    }
  }
];

3. 组件内守卫

在组件内使用:

<!-- src/views/Admin.vue -->
<template>
  <h1>管理面板</h1>
</template>

<script>
import { useRouter } from 'vue-router';

export default {
  setup() {
    const router = useRouter();

    router.beforeEach((to, from, next) => {
      if (to.path === '/admin' && !isAuthenticated()) {
        next('/login');
      } else {
        next();
      }
    });
  }
};
</script>
  • 注意:组件内守卫需谨慎使用,避免重复注册。

综合示例

路由配置

// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', name: 'Home', component: () => import('@/views/Home.vue') },
  { 
    path: '/product/:id', 
    name: 'Product', 
    component: () => import('@/views/Product.vue'),
    meta: { requiresAuth: true }
  },
  { path: '/login', name: 'Login', component: () => import('@/views/Login.vue') },
  { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('@/views/NotFound.vue') }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

router.beforeEach((to, from, next) => {
  const isLoggedIn = !!localStorage.getItem('token');
  if (to.meta.requiresAuth && !isLoggedIn) {
    next('/login');
  } else {
    next();
  }
});

export default router;

组件实现

Home.vue

<template>
  <div>
    <h1>首页</h1>
    <router-link :to="{ name: 'Product', params: { id: 1 } }">产品 1</router-link>
  </div>
</template>

Product.vue

<template>
  <div>
    <h1>产品 {{ route.params.id }}</h1>
    <button @click="logout">退出</button>
  </div>
</template>

<script>
import { useRoute, useRouter } from 'vue-router';

export default {
  setup() {
    const route = useRoute();
    const router = useRouter();

    const logout = () => {
      localStorage.removeItem('token');
      router.push('/login');
    };

    return { route, logout };
  }
};
</script>

Login.vue

<template>
  <div>
    <h1>登录</h1>
    <button @click="login">登录</button>
  </div>
</template>

<script>
import { useRouter } from 'vue-router';

export default {
  setup() {
    const router = useRouter();

    const login = () => {
      localStorage.setItem('token', 'dummy-token');
      router.push('/');
    };

    return { login };
  }
};
</script>
  • 效果:
    • 未登录访问 /product/1 跳转到 /login。
    • 登录后可访问产品页面,退出后重定向。

应用场景

  1. 动态路由:
    • 用户详情、文章页面(如 /post/:id)。
  2. 路由守卫:
    • 权限控制、数据预加载(如导航前加载用户信息)。
  3. 404 处理:
    • 通配符路由捕获无效路径。

注意事项

  1. 参数变化:
    • 动态参数变化时组件不会重新渲染,需监听 route:
      watch(() => route.params.id, (newId) => {
        // 更新数据
      });
      
  2. 守卫顺序:
    • 全局 -> 路由独享 -> 组件内,按序执行。
  3. 性能:
    • 避免复杂守卫逻辑影响导航速度。

总结

动态路由通过参数实现灵活页面渲染,路由守卫则提供了强大的导航控制能力。结合 Vue Router 4 的 API,你可以轻松实现动态导航和权限管理。本节的实践为你打下了坚实基础,下一节将探讨嵌套路由与懒加载,进一步丰富你的路由技能!

Last Updated:: 2/24/25, 12:59 PM