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;
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
属性实现组件的嵌套展示,叫做嵌套路由。嵌套路由允许在一个组件中嵌套展示子组件。
# 2-1 组件嵌套结构示意图
假设项目的组件嵌套关系如下:
App.vue
└── <router-view> (根路由)
├── HomeComponent (路径: /home)
└── AboutComponent (路径: /about)
└── <router-view> (子路由)
├── Tab1Component (路径: /about/tab1)
└── Tab2Component (路径: /about/tab2)
2
3
4
5
6
7
# 2-2 嵌套路由的定义步骤
选择父路由
确定需要子路由的父路由,这个路由将作为子路由的容器。
例如,如果你有一个
AboutComponent
需要在其下展示多个子页面,比如Tab1Component
和Tab2Component
,那么AboutComponent
就是父路由。
定义子路由 (
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
中定义的路径是相对于父路由的。
- 在父路由的
在父组件中放置子路由的占位符
- 在父路由对应的组件内部,放置
<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
时才会显示。
- 在父路由对应的组件内部,放置
创建子路由链接
- 子路由的导航链接可以放在父组件内,也可以放在任何可以进行导航的地方,只需正确指向子路由路径。
<!-- 在父组件中添加子路由链接 --> <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; // 导出路由实例
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>
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. 动态路由匹配
在一些应用中,我们可能会遇到多个类似的路由,例如访问不同用户的页面。这时候如果每个用户都要定义一个路由规则,代码会非常冗余。动态路由可以解决这个问题。
# 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;
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>
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;
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>
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 中,导航有两种方式:声明式导航和编程式导航。
# 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>
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>
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 中的查询字符串部分,例如过滤条件、搜索关键字等。
- 简便性:当参数只是查询字符串的一部分,而不需要动态路由匹配时。
- 直接传递字符串路径
this.$router.push('/路径?参数名1=参数值1&参数名2=参数值2');
- 使用对象传递路径和查询参数
this.$router.push({
path: '/home',
query: {
param1: 'value1',
param2: 'value2'
}
}); // 跳转到 /home 并附加查询字符串 ?param1=value1¶m2=value2
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>
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
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>
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>
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-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>
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>
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 导航守卫简介
导航守卫用于控制路由的访问权限。它们可以在路由进入、更新或离开时执行一些操作,常用于权限控制和数据预处理。
# 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;
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
函数的方式,可以实现不同的导航行为:
next()
:放行,进入下一个导航。next(false)
:中断当前导航,保持在当前路由(不会跳转)。next('/path')
或next({ path: '/path' })
:跳转到一个新的路由。
router.beforeEach((to, from, next) => {
// 放行
next();
// 中断当前导航
next(false);
// 跳转到新的路由
next('/login');
});
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;
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;
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') // 捕获所有未匹配的路由
}
];
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') // 捕获所有未匹配的路由
}
];
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;
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;
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
使用:
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');
});
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/;
}
}
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
});
2
3
4