程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

    • Vue简介
    • Vue 基础使用
    • Vue的基础指令
    • 过滤器(Filters)
    • 侦听器(Watch)
    • 计算属性(computed)
    • vue-cli
    • vue.config.js配置
    • Vue组件
    • 生命周期和数据共享
    • Vue 组件实例与数据代理 (this)
    • $refs 引用
    • 动态组件
    • 插槽 (Slots)
    • 混入 (Mixin)
    • 自定义指令 (directives)
    • 插件 (Plugins)
    • 初识Vue-router
    • Vue-router的常见用法
      • 1. 路由重定向 (redirect)
      • 2. 嵌套路由 (children)
        • 2-1 组件嵌套结构示意图
        • 2-2 嵌套路由的定义步骤
      • 3. 一个路由中定义多个组件
        • 3-1 路由命名视图概述
        • 3-2 示例代码
        • 3-3 使用命名视图
      • 4. 动态路由匹配
        • 4-1 动态路由的概念
        • 4-2 动态路由参数的访问 (this.$route.params)
        • 4-3 使用 props 接收动态路由参数
      • 5. 声明式导航 & 编程式导航
        • 5-1 声明式导航
        • 1. 使用字符串
        • 2. 使用对象
        • 5-2 编程式导航 API
        • 5-3 $router.push
        • 1. 使用路径拼接和查询字符串跳转
        • 2. 使用命名路由和 params 跳转
        • 5-4 $router.replace
        • 5-5 $router.go
        • 5-6 $router.go 的简化用法
        • 5-7 导航守卫简介
        • 5-8 全局前置导航守卫
        • 5-9 守卫方法的 3 个形参
        • 5-10 next 函数的 3 种调用方式
        • 5-11 路由守卫控制后台主页的访问权限
        • 1. 基于路径判断的全局前置守卫
        • 2. 基于路由元信息的全局前置守卫
        • 5-12 关于meta 字段
        • 1. 统一设置需要验证的路由
        • 2. 使用父路由统一设置 `meta` 属性
        • 3. 通过动态判断来简化设置
      • 6. 路由器的两种工作模式
        • 1. 什么是 Hash 值?
        • 2. Hash 模式
        • 3. History 模式
        • 4. History 模式的服务器配置
        • Node.js 环境配置
        • Nginx 环境配置
        • 5. 切换路由模式
  • Vue3

  • vue3 + TS 项目集成

  • Vue全家桶
  • Vue2
scholar
2024-08-01
目录

Vue-router的常见用法

# Vue-router的常见用法

# 1. 路由重定向 (redirect)

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 B,从而展示特定的组件页面。通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向。

示例代码













 

















// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeComponent from '../components/HomeComponent.vue';
import AboutComponent from '../components/AboutComponent.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    redirect: '/home' // 当访问根路径时,重定向到 /home 路径
  },
  {
    path: '/home',
    component: HomeComponent
  },
  {
    path: '/about',
    component: AboutComponent
  }
];

const router = new VueRouter({
  routes // 注入路由配置
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 2. 嵌套路由 (children)

通过路由的 children 属性实现组件的嵌套展示,叫做嵌套路由。嵌套路由允许在一个组件中嵌套展示子组件。

image-20240731210639617

# 2-1 组件嵌套结构示意图

假设项目的组件嵌套关系如下:




 

 
 

App.vue
 └── <router-view> (根路由)
      ├── HomeComponent (路径: /home)
      └── AboutComponent (路径: /about)
           └── <router-view> (子路由)
                ├── Tab1Component (路径: /about/tab1)
                └── Tab2Component (路径: /about/tab2)
1
2
3
4
5
6
7

# 2-2 嵌套路由的定义步骤

  1. 选择父路由

    • 确定需要子路由的父路由,这个路由将作为子路由的容器。

    • 例如,如果你有一个 AboutComponent 需要在其下展示多个子页面,比如 Tab1Component 和 Tab2Component,那么 AboutComponent 就是父路由。

  2. 定义子路由 (src/router/index.js)

    • 在父路由的 children 属性中,添加子路由的路径和对应的组件。
    • 如果 children 数组中的某个路由规则的 path 值为空字符串,则这条路由规则称为“默认子路由”。当用户访问父路由时,默认子路由会被自动激活。




     

     
     


     
     


     
     





    const routes = [
      {
        path: '/about', // 父路由路径
        component: AboutComponent, // 父路由对应的组件
        children: [ // 子路由配置
          {
            path: '', // 默认子路由
            component: DefaultComponent // 当访问 /about 时,默认渲染 DefaultComponent
          },
          {
            path: 'tab1', // 子路由的路径,不需要加斜杠
            component: Tab1Component // Tab1Component 为 /about/tab1 的子路由组件
          },
          {
            path: 'tab2',
            component: Tab2Component // Tab2Component 为 /about/tab2 的子路由组件
          }
        ]
      }
    ];
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    • 注意:在 children 中定义的路径是相对于父路由的。
  3. 在父组件中放置子路由的占位符

    • 在父路由对应的组件内部,放置 <router-view>,用于渲染当前激活的子路由组件。




     
     



    <!-- AboutComponent.vue -->
    <template>
      <div>
        <h1>关于我们</h1>
        <!-- 子路由的占位符 -->
        <router-view></router-view>
      </div>
    </template>
    
    1
    2
    3
    4
    5
    6
    7
    8
    • 这些组件通过 AboutComponent 中的 <router-view> 渲染,只有在访问 /about/tab1 或 /about/tab2 时才会显示。
  4. 创建子路由链接

    • 子路由的导航链接可以放在父组件内,也可以放在任何可以进行导航的地方,只需正确指向子路由路径。
     





     





    <!-- 在父组件中添加子路由链接 -->
    <nav>
      <router-link to="/about/tab1">Tab 1</router-link> <!-- 导航到 Tab1 -->
      <router-link to="/about/tab2">Tab 2</router-link> <!-- 导航到 Tab2 -->
    </nav>
    
    <!-- 或者在其他组件中也可以定义这些链接 -->
    <nav>
      <router-link to="/about/tab1">Tab 1</router-link>
      <router-link to="/about/tab2">Tab 2</router-link>
    </nav>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

注意

除了使用声明式导航(如 <router-link>)之外,还可以使用编程式导航来控制路由跳转。编程式导航常用于处理导航逻辑需要在 JavaScript 中进行操作的场景。

# 3. 一个路由中定义多个组件

# 3-1 路由命名视图概述

路由命名视图通过在 components 对象中定义多个组件,使得一个路由可以对应多个视图。在视图中,通过 <router-view> 元素来渲染这些组件。

# 3-2 示例代码

下面是一个使用命名视图的示例代码,展示如何在一个路由中定义多个组件。



















 
 














// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeComponent from '../components/HomeComponent.vue'; // 导入 Home 组件
import AboutComponent from '../components/AboutComponent.vue'; // 导入 About 组件
import SidebarComponent from '../components/SidebarComponent.vue'; // 导入 Sidebar 组件

Vue.use(VueRouter); // 使用 VueRouter 插件

const routes = [
  {
    path: '/',
    redirect: '/home' // 当访问根路径时,重定向到 /home 路径
  },
  {
    path: '/home',
    components: {
      default: HomeComponent, // 默认视图,显示 Home 组件
      sidebar: SidebarComponent // 命名视图,显示 Sidebar 组件
    }
  },
  {
    path: '/about',
    component: AboutComponent // 仅显示 About 组件
  }
];

const router = new VueRouter({
  routes // 注入路由配置
});

export default router; // 导出路由实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 3-3 使用命名视图

在 App.vue 中,通过 <router-view> 元素来渲染路由定义的多个视图:










 
 
 



















<!-- src/App.vue -->
<template>
  <div id="app">
    <h1>My Vue App</h1>
    <!-- 声明路由链接 -->
    <nav>
      <router-link to="/">Home</router-link> <!-- 链接到根路径,会被重定向到 /home -->
      <router-link to="/about">About</router-link> <!-- 链接到 /about 路径 -->
    </nav>
    <!-- 声明路由占位符 -->
    <router-view></router-view> <!-- 默认视图占位符 -->
    <router-view name="sidebar"></router-view> <!-- 命名视图占位符 -->
  </div>
</template>

<script>
export default {
  name: 'App'
};
</script>

<style scoped>
nav {
  margin-bottom: 20px; /* 为导航栏添加底部边距 */
}

h1 {
  color: #42b983; /* 标题的颜色 */
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  • 默认视图:通过 <router-view> 元素渲染,不需要指定 name 属性,用于显示默认组件。
  • 命名视图:通过在 <router-view> 元素上指定 name 属性来定义,用于显示指定名称的组件。
  • 使用场景:适用于复杂的页面布局,比如需要同时显示主内容和侧边栏的情况。

注意事项

  • 命名视图的名称可以是任意字符串,但必须与路由配置中的 components 对象的键名一致。
  • 一个页面中可以使用多个 <router-view> 元素,每个元素都可以渲染不同的组件。
  • 如果没有为 <router-view> 指定 name 属性,则默认渲染 default 视图。

# 4. 动态路由匹配

在一些应用中,我们可能会遇到多个类似的路由,例如访问不同用户的页面。这时候如果每个用户都要定义一个路由规则,代码会非常冗余。动态路由可以解决这个问题。

image-20240803042925820

# 4-1 动态路由的概念

动态路由指的是在路由路径中使用变量,将路径中可变的部分定义为参数项,从而提高路由规则的复用性。在 Vue Router 中,使用英文的冒号(:)来定义动态路由参数。

示例代码

假设我们有三个用户页面,访问路径分别是 /user/1、/user/2 和 /user/3。可以通过动态路由来定义这些路径。











 











// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import UserComponent from '../components/UserComponent.vue'; // 导入用户组件

Vue.use(VueRouter);

const routes = [
  {
    path: '/user/:id', // 动态路由,:id 表示动态参数
    component: UserComponent,
    props: true // 开启 props 传参
  }
];

const router = new VueRouter({
  routes // 注入路由配置
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在这个示例中,我们定义了一个动态路由 /user/:id,其中 :id 是动态参数,可以匹配任意的用户 ID。

动态路由参数的作用

  • 路径中的占位符::id 是一个占位符,表示路径中的动态部分,可以是任意值。
  • 参数的传递:动态路由参数通常用于标识不同的资源,例如用户 ID、文章 ID 等。这些参数会传递给后端,用于获取对应的数据。
  • 复用性:使用动态路由可以避免重复定义相似的路由规则,提高代码的复用性。例如,/user/:id 可以匹配 /user/1、/user/2 等多个路径,只需要定义一条路由规则。

注意

在使用动态路由时,如果路由路径中包含动态参数(例如 :id),切换到该路由时必须传入对应的参数,否则会导致路由匹配失败,从而无法显示对应的组件。

您说得对,上面的示例中关于如何访问动态路由参数的实现方式可以有所改进。动态路由参数通常通过 this.$route.params 来访问,而不是直接通过 props。让我们来重新整理一下这个示例。

# 4-2 动态路由参数的访问 (this.$route.params)

在动态路由渲染出来的组件中,可以通过 this.$route.params 对象访问到动态路由中的参数值。















 



 










<!-- src/components/UserComponent.vue -->
<template>
  <div>
    <h2>用户信息</h2>
    <p>用户 ID: {{ userId }}</p> <!-- 显示用户 ID -->
  </div>
</template>

<script>
export default {
  name: 'UserComponent',
  computed: {
    userId() {
      // 通过 this.$route.params 访问动态路由参数
      return this.$route.params.id;
    }
  },
  created() {
    console.log('User ID:', this.userId); // 在组件创建时访问动态路由参数
  }
};
</script>

<style scoped>
h2 {
  color: #42b983; /* 标题颜色 */
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • 动态路由参数:当在路由配置中定义动态路由时,使用占位符(例如 /user/:id)来表示动态部分。在组件中可以通过 this.$route.params 访问传递的参数。
  • computed 属性:在示例中使用 computed 属性来访问 userId,确保在任何时候都能获取到最新的参数值。
  • 示例输出:在模板中显示 用户 ID,并在控制台打印 User ID。

上述示例通过 $route.params 来访问动态路由参数,这种方式不需要显式地通过 props 接收路由参数,直接使用路由的内置功能即可完成数据传递。

# 4-3 使用 props 接收动态路由参数

在 Vue Router 中,可以通过配置路由规则中的 props 属性,将动态路由参数作为 props 传递给组件。这种方式使得代码更加简洁,直接使用 this.id 访问参数值,而不需要每次都使用 this.$route.params.id 来获取动态参数。

示例代码

在 src/router/index.js 中设置路由规则:









 
 
 









import Vue from 'vue';
import VueRouter from 'vue-router';
import UserComponent from '../components/UserComponent.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/user/:id', // 动态路由,:id 表示动态参数
    component: UserComponent,
    props: true // 开启 props 传参
  }
];

const router = new VueRouter({
  routes // 注入路由配置
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在这个示例中,我们定义了一个动态路由 /user/:id,其中 :id 是一个占位符,用于表示动态参数。通过设置 props: true,路由参数将作为 props 传递给组件 UserComponent。

在组件中接收 props

当路由跳转到该组件时,可以通过定义 props 属性来接收传递过来的路由参数:











 
 
 
 
 
 










<template>
  <div>
    <h1>用户信息</h1>
    <p>用户 ID: {{ id }}</p> <!-- 直接使用 props 中的 id -->
  </div>
</template>

<script>
export default {
  name: 'UserComponent',
  props: {
    id: {
      type: String,
      required: true // 确保 id 是必需的 props
    }
  },
  created() {
    console.log(this.id); // 打印 id 参数
  }
};
</script>

<style scoped>
/* 样式 */
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在这个示例中,组件 UserComponent 通过 props 接收动态路由参数 id,使得代码更加简洁和直观。

# 5. 声明式导航 & 编程式导航

在 Vue Router 中,导航有两种方式:声明式导航和编程式导航。

image-20240801004904786

# 5-1 声明式导航

声明式导航是指在模板中使用 <router-link> 组件来进行页面导航。这种方式类似于 HTML 中的 <a> 标签,适合大多数简单的导航需求。在 Vue 2 和 Vue 3 中,<router-link> 的 to 属性可以接收字符串或对象。

# 1. 使用字符串

<template>
  <div>
    <!-- 声明式导航:使用字符串 -->
    <router-link to="/user/123">Go to User</router-link>
  </div>
</template>

<script>
export default {
  name: 'Example'
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
  • 字符串方式:直接指定要跳转的路径。

# 2. 使用对象

<template>
  <div>
    <!-- 声明式导航:使用对象 -->
    <router-link :to="{ path: '/user', query: { id: userId } }">Go to User with Query</router-link>
    <router-link :to="{ name: 'user', params: { id: userId } }">Go to User with Params</router-link>
  </div>
</template>

<script>
export default {
  data() {
    return {
      userId: 123 // 用户 ID,传递给路由作为参数
    };
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • 对象方式:可以更加灵活地指定导航的路径和参数。
    • path:指定要跳转的路径。
    • query:指定查询参数,生成 URL 如 /user?id=123。
    • name:使用命名路由进行导航。
    • params:传递动态路由参数。注意:如果使用 path,不能同时使用 params。

笔记

  • 备注1:传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path。

  • 备注2:传递params参数时,需要提前在路由路径中通过 : 语法指定占位符,以接受动态参数。

# 5-2 编程式导航 API

编程式导航是通过 JavaScript 代码调用 Vue Router 实例的方法实现的。可以使用 this.$router 实例来进行编程式导航。

常用的编程式导航 API 包括:

  • this.$router.push(location):导航到一个新的 URL,并在 history 栈中增加新的历史记录
  • this.$router.replace(location):导航到一个新的 URL,并替换当前的历史记录。
  • this.$router.go(n):在 history 栈中前进或后退 n 步,实现导航栏历史前进、后退。

# 5-3 $router.push

调用 this.$router.push() 方法,可以跳转到指定的 URL,从而展示对应的组件页面。$router.push 可以接收一个字符串路径或者是一个包含路径、参数等信息的对象。它会向浏览器历史记录添加一个新的记录,因此在用户点击浏览器的“后退”按钮时,可以返回到之前的页面。

# 1. 使用路径拼接和查询字符串跳转

使用场景

  • 显式参数:需要将参数显式地显示在 URL 中的查询字符串部分,例如过滤条件、搜索关键字等。
  • 简便性:当参数只是查询字符串的一部分,而不需要动态路由匹配时。
  1. 直接传递字符串路径
this.$router.push('/路径?参数名1=参数值1&参数名2=参数值2');
1
  1. 使用对象传递路径和查询参数
this.$router.push({
  path: '/home',
  query: {
    param1: 'value1',
    param2: 'value2'
  }
}); // 跳转到 /home 并附加查询字符串 ?param1=value1&param2=value2
1
2
3
4
5
6
7

在这种方式下,可以通过 this.$route.query 获取查询参数。

示例代码




 
 
 








 


 


 
 
 
 
 
 












<template>
  <div>
    <h1>编程式导航示例</h1>
    <button @click="goHome">Go to Home</button>
    <button @click="goAbout">Go to About</button>
    <button @click="search">Search</button>
  </div>
</template>

<script>
export default {
  name: 'NavigationExample',
  methods: {
    goHome() {
      this.$router.push('/'); // 导航到首页
    },
    goAbout() {
      this.$router.push('/about'); // 导航到关于页
    },
    search() {
      this.$router.push({
        path: '/search',
        query: {
          keyword: 'Vue',
          page: 1
        }
      }); // 导航到搜索页,并传递查询参数
    }
  }
};
</script>

<style scoped>
button {
  margin-right: 10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

在这个示例中,我们定义了三个按钮,每个按钮点击时调用 this.$router.push() 方法导航到不同的页面。

# 2. 使用命名路由和 params 跳转

  • 当你需要传递动态路由参数时去展示对应的组件页面时,必须使用命名路由和 params的写法,
  • 注意:使用params跳转时,需要提前在路由路径中通过 : 语法指定占位符,以接受动态参数。
this.$router.push({
  name: 'user', // 指定命名路由
  params: {
    userId: 123 // 传递动态路由参数 userId
  }
}); // 跳转到名为 'user' 的路由,并传递动态路由参数 userId
1
2
3
4
5
6

在这种方式下,可以通过 this.$route.params 获取动态路由中的参数值。

使用场景

  • 参数不可见:参数不需要显示在 URL 中的查询字符串部分,或者参数是路由路径的一部分。
  • 动态参数:需要传递的参数作为路径的一部分,例如用户 ID、文章 ID 等。

示例代码




 
 
 
 








 


 


 
 
 
 
 
 
 


 
 
 
 
 
 











<template>
  <div>
    <h1>编程式导航示例</h1>
    <button @click="goHome">Go to Home</button>
    <button @click="goAbout">Go to About</button>
    <button @click="search">Search</button>
    <button @click="goUser">Go to User</button>
  </div>
</template>

<script>
export default {
  name: 'NavigationExample',
  methods: {
    goHome() {
      this.$router.push('/'); // 导航到首页
    },
    goAbout() {
      this.$router.push('/about'); // 导航到关于页
    },
    search() {
      this.$router.push({
        path: '/search',
        query: {
          keyword: 'Vue',
          page: 1
        }
      }); // 导航到搜索页,并传递查询参数
    },
    goUser() {
      this.$router.push({
        name: 'user',
        params: {
          userId: 123
        }
      }); // 导航到用户页,并传递路由参数
    }
  }
};
</script>

<style scoped>
button {
  margin-right: 10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

在这个示例中,我们定义了四个按钮,每个按钮点击时调用 this.$router.push() 方法导航到不同的页面,并传递查询参数或路由参数。

# 5-4 $router.replace

this.$router.replace() 方法导航到一个新的 URL,不会在 history 栈中增加新记录。这意味着无法通过浏览器的回退按钮回到之前的页面。




 
 








 


 











<template>
  <div>
    <h1>编程式导航示例</h1>
    <button @click="replaceHome">Replace to Home</button>
    <button @click="replaceAbout">Replace to About</button>
  </div>
</template>

<script>
export default {
  name: 'NavigationExample',
  methods: {
    replaceHome() {
      this.$router.replace('/'); // 导航到首页,替换当前记录
    },
    replaceAbout() {
      this.$router.replace('/about'); // 导航到关于页,替换当前记录
    }
  }
};
</script>

<style scoped>
button {
  margin-right: 10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

image-20240731212959689

# 5-5 $router.go

调用 this.$router.go() 方法,可以在浏览历史中前进或后退。




 
 








 


 











<template>
  <div>
    <h1>编程式导航示例</h1>
    <button @click="goBack">Go Back</button>
    <button @click="goForward">Go Forward</button>
  </div>
</template>

<script>
export default {
  name: 'NavigationExample',
  methods: {
    goBack() {
      this.$router.go(-1); // 后退一页
    },
    goForward() {
      this.$router.go(1); // 前进一步
    }
  }
};
</script>

<style scoped>
button {
  margin-right: 10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 5-6 $router.go 的简化用法

this.$router.go() 方法的简化用法包括:

  • this.$router.back():后退一页。
  • this.$router.forward():前进一步。



 
 








 


 











<template>
  <div>
    <h1>编程式导航示例</h1>
    <button @click="goBack">Go Back</button>
    <button @click="goForward">Go Forward</button>
  </div>
</template>

<script>
export default {
  name: 'NavigationExample',
  methods: {
    goBack() {
      this.$router.back(); // 后退一页
    },
    goForward() {
      this.$router.forward(); // 前进一步
    }
  }
};
</script>

<style scoped>
button {
  margin-right: 10px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 5-7 导航守卫简介

导航守卫用于控制路由的访问权限。它们可以在路由进入、更新或离开时执行一些操作,常用于权限控制和数据预处理。

image-20240731212849075

# 5-8 全局前置导航守卫

全局前置守卫会在每次发生路由导航跳转时触发,可以在这里对每个路由进行访问权限的控制。




















 
 
 
 
 



// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeComponent from '../components/HomeComponent.vue';
import AboutComponent from '../components/AboutComponent.vue';

Vue.use(VueRouter);

const routes = [
  { path: '/', component: HomeComponent },
  { path: '/about', component: AboutComponent }
];

const router = new VueRouter({
  routes
});

// 定义全局前置守卫
router.beforeEach((to, from, next) => {
  console.log('全局前置守卫:', to, from);
  // 放行所有路由
  next();
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

在这个示例中,to.meta.requiresAuth 用于检查路由是否需要身份验证,如果需要验证但没有 token,则跳转到登录页面。

# 5-9 守卫方法的 3 个形参

全局前置守卫的回调函数中接收 3 个形参:

  • to:目标路由对象,表示即将要进入的目标路由对象。
  • from:当前导航正要离开的路由对象。
  • next:函数,表示放行,调用该函数后才能继续进行导航。

to 和 from 对象的常用属性:

属性 类型 描述
path String 当前路由的路径,例如 /home。
params Object 一个 key/value 对象,表示动态路由参数。
query Object 一个 key/value 对象,表示查询参数。
name String 当前路由的名称。
meta Object 当前路由的元数据对象。
hash String 当前路由的 hash 值,例如 #info。
fullPath String 完整解析后的 URL,包括查询参数和 hash 值。
matched Array 一个数组,包含当前路由的所有嵌套路径片段的路由记录。

# 5-10 next 函数的 3 种调用方式

根据调用 next 函数的方式,可以实现不同的导航行为:

  1. next():放行,进入下一个导航。
  2. next(false):中断当前导航,保持在当前路由(不会跳转)。
  3. next('/path') 或 next({ path: '/path' }):跳转到一个新的路由。
router.beforeEach((to, from, next) => {
  // 放行
  next();

  // 中断当前导航
  next(false);

  // 跳转到新的路由
  next('/login');
});
1
2
3
4
5
6
7
8
9
10

# 5-11 路由守卫控制后台主页的访问权限

# 1. 基于路径判断的全局前置守卫

import Vue from 'vue';
import VueRouter from 'vue-router';
import NProgress from 'nprogress';
import { Message } from 'element-ui';

Vue.use(VueRouter);

const routes = [
  // 路由配置
];

const router = new VueRouter({
  mode: 'history',
  routes
});

router.beforeEach((to, from, next) => {
  // 检查目标路由是否需要身份验证
  if (to.path !== '/login') {
    const user = localStorage.getItem('user') || sessionStorage.getItem('user');
    if (user && user.token) {
      next(); // 用户已登录,放行
    } else {
      Message.error('token已失效,请重新登录'); // 统一提示
      next('/login'); // 跳转到登录页
    }
  } else {
    next(); // 不需要身份验证,放行
  }
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 2. 基于路由元信息的全局前置守卫

import Vue from 'vue';
import VueRouter from 'vue-router';
import NProgress from 'nprogress';
import { Message } from 'element-ui';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    redirect: '/login',
  },
  {
    path: '/main',
    component: () => import('@/view/Container.vue'),
    children: [
      {
        path: 'home',
        component: () => import('@/view/Home.vue'),
        meta: { requiresAuth: true, name: '系统首页' } // 需要身份验证
      },
      // 更多路由配置
    ]
  },
  {
    path: '/login',
    component: () => import('@/view/Login.vue')
  },
  {
    path: '*',
    component: () => import('@/view/404.vue')  // 捕获所有未匹配的路由
  }
];

const router = new VueRouter({
  mode: 'history',
  routes
});

router.beforeEach((to, from, next) => {
  // 检查目标路由是否需要身份验证
  if (to.meta.requiresAuth) {
    const user = localStorage.getItem('user') || sessionStorage.getItem('user');
    if (user && user.token) {
      next(); // 用户已登录,放行
    } else {
      Message.error('请先登录!'); // 统一提示
      next('/login'); // 跳转到登录页
    }
  } else {
    next(); // 不需要身份验证,放行
  }
});
export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

适用场景建议

  • 如果项目中的所有需要身份验证的页面都可以通过路径简单判断(例如,只有 /login 页面不需要验证),可以使用方式一。
  • 如果项目中有多个页面需要灵活配置是否需要身份验证,建议使用方式二,通过元信息控制验证,更加灵活。

# 5-12 关于meta 字段

在 Vue.js 项目中使用全局前置守卫来处理路由的身份验证时,可以通过在 meta 字段中设置 requiresAuth 属性来标记哪些路由需要进行身份验证。对于有很多路由的情况,手动在每个路由中设置 meta 属性确实比较繁琐,但有一些策略可以帮助你减少重复劳动并简化管理。

# 1. 统一设置需要验证的路由

如果你的应用中有多个路由需要身份验证,你可以考虑将这些路由统一放在一个数组或对象中进行管理,然后通过遍历的方式为它们批量添加 requiresAuth 属性。例如:

// 需要身份验证的路由
const protectedRoutes = [
  {
    path: 'home',
    component: () => import('@/view/Home.vue'),
    meta: {
      name: '系统首页'
    }
  },
  {
    path:'about',
    component:() => import('@/view/About.vue'),
    meta:{
      name:'表格数据'
    }
  },
  {
    path:'report',
    component: () => import('@/view/Report.vue'),
    meta: {
      name: '报告管理'
    }
  },
  // 其他需要验证的路由...
];

// 遍历设置 `requiresAuth` 属性
protectedRoutes.forEach(route => {
  route.meta = { ...route.meta, requiresAuth: true };
});

// 公开访问的路由
const publicRoutes = [
  {
    path: '/login',
    component: () => import('@/view/Login.vue')
  },
  {
    path: '/register',
    component: () => import('@/view/Register.vue')
  },
  // 其他公开路由...
];

// 合并所有路由
const routes = [
  {
    path: '/',
    redirect: '/login',
  },
  {
    path: '/main',
    redirect: '/main/home',
  },
  {
    path: '/main',
    component: () => import('@/view/Container.vue'),
    children: [...protectedRoutes]
  },
  ...publicRoutes,
  {
    path: '*',
    component: () => import('@/view/404.vue')  // 捕获所有未匹配的路由
  }
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

# 2. 使用父路由统一设置 meta 属性

如果有一个父路由,其下的所有子路由都需要身份验证,可以将 requiresAuth 属性放在父路由的 meta 中。这样,子路由会继承这个属性:

const routes = [
  {
    path: '/',
    redirect: '/login',
  },
  {
    path: '/main',
    component: () => import('@/view/Container.vue'),
    meta: { requiresAuth: true }, // 父路由统一设置
    children:[
      {
        path: 'home',
        component: () => import('@/view/Home.vue'),
        meta:{
          name:'系统首页'
        }
      },
      {
        path:'about',
        component:() => import('@/view/About.vue'),
        meta:{
          name:'表格数据'
        }
      },
      // 其他子路由...
    ]
  },
  {
    path: '/login',
    component: () => import('@/view/Login.vue')
  },
  {
    path: '/register',
    component: () => import('@/view/Register.vue')
  },
  {
    path: '*',
    component: () => import('@/view/404.vue')  // 捕获所有未匹配的路由
  }
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 3. 通过动态判断来简化设置

如果你有一些规则来判断哪些路由需要身份验证,可以在全局守卫中进行动态判断,而不依赖 meta 属性。例如,你可以通过路径名称、路由层级或其他逻辑来决定是否需要验证。

总结

  • 手动设置:在每个需要身份验证的路由中手动添加 meta 属性。
  • 批量设置:将所有需要验证的路由放在一起批量添加 meta 属性。
  • 父路由统一设置:将 requiresAuth 属性设置在父路由中,子路由自动继承。
  • 动态判断:在全局守卫中动态判断是否需要验证,而不依赖 meta。

# 6. 路由器的两种工作模式

Vue Router 支持两种工作模式:Hash 模式和 History 模式。这两种模式决定了 URL 的结构和处理方式。

# 1. 什么是 Hash 值?

Hash 值指的是 URL 中 # 及其后面的内容。

  • 示例:在 URL http://example.com/#/home 中,#/home 就是 Hash 值。
  • 特点:Hash 值不会包含在 HTTP 请求中,不会被发送到服务器。

# 2. Hash 模式

Hash 模式是 Vue Router 的默认模式,通过 URL 中的 # 来保持页面路径。

  • 优点:

    • 简单易用,默认即为 Hash 模式。
    • 兼容性好,支持所有浏览器。
    • 不需要额外的服务器配置。
  • 缺点:

    • 地址中永远带着 # 号,不美观。
    • 如果将地址通过第三方手机应用程序分享,可能会被标记为不合法。

示例代码:
















 





// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeComponent from '../components/HomeComponent.vue';
import AboutComponent from '../components/AboutComponent.vue';

Vue.use(VueRouter);

const routes = [
  { path: '/', component: HomeComponent },
  { path: '/about', component: AboutComponent }
];

const router = new VueRouter({
  mode: 'hash', // 使用 Hash 模式
  routes
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 3. History 模式

History 模式使用 HTML5 的 History API 来实现无 # 号的 URL,这种模式更接近传统的网站 URL 结构。

  • 优点:

    • 地址更加干净和美观。
    • 更符合现代 Web 应用的 URL 结构。
  • 缺点:

    • 兼容性较差,不支持所有浏览器。
    • 需要服务器配置支持,解决刷新页面服务端 404 的问题。

示例代码:
















 





// src/router/index.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeComponent from '../components/HomeComponent.vue';
import AboutComponent from '../components/AboutComponent.vue';

Vue.use(VueRouter);

const routes = [
  { path: '/', component: HomeComponent },
  { path: '/about', component: AboutComponent }
];

const router = new VueRouter({
  mode: 'history', // 使用 History 模式
  routes
});

export default router;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 4. History 模式的服务器配置

# Node.js 环境配置

在 Node.js 环境中,可以使用 connect-history-api-fallback 中间件来解决刷新页面时的 404 问题。

安装:

npm install connect-history-api-fallback --save
1

使用:

const express = require('express');
const history = require('connect-history-api-fallback');

const app = express();
app.use(history());
app.use(express.static('dist'));

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
1
2
3
4
5
6
7
8
9
10

# Nginx 环境配置

在 Nginx 环境中,可以通过配置重写规则来支持 History 模式。

示例配置:

server {
  listen 80;
  server_name example.com;

  location / {
    try_files $uri $uri/ /index.html;
  }

  location /static/ {
    alias /path/to/static/files/;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 5. 切换路由模式

通过在 Vue Router 配置中设置 mode 属性,可以在 Hash 模式和 History 模式之间切换。默认情况下是 Hash 模式。

示例:


 



const router = new VueRouter({
  mode: 'history', // 切换为 History 模式
  routes
});
1
2
3
4
编辑此页 (opens new window)
上次更新: 2025/01/30, 23:55:43
初识Vue-router
初识Vue3

← 初识Vue-router 初识Vue3→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式