路由
首先我们看一下Vue 2 与 Vue 3 路由对比图:
特性 | Vue 2 | Vue 3 |
---|---|---|
路由库版本 | vue-router 3.x | vue-router 4.x |
路由实例创建 | new VueRouter() | createRouter() 和 createWebHistory() |
路由模式设置 | mode: 'history' | history: createWebHistory() |
路由信息获取 | this.$route 和 this.$router | useRoute() 和 useRouter() |
插件使用 | Vue.use(VueRouter) | app.use(router) |
组合式 API 支持 | 不支持 | 支持 |
代码分割与懒加载 | 通过 import() 进行代码分割 | 通过 import() 和 defineAsyncComponent |
动态路由和命名视图支持 | 支持 | 支持 |
路由守卫与导航钩子 | 支持 | 支持 (组合式 API ) |
对象形式的 props 传参支持 | 支持 | 支持(语法稍有改进) |
# 1. 路由库版本
- Vue 2 使用
vue-router
3.x:与 Vue 2 一起使用的路由版本。 - Vue 3 使用
vue-router
4.x:专为 Vue 3 设计,结合组合式 API。
# 2. vue3路由实例创建
- 在 Vue 2 中,使用
new VueRouter()
来创建路由实例。 - 在 Vue 3 中,使用
createRouter()
和createWebHistory()
来创建路由实例。
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import Home from './components/Home.vue';
import About from './components/About.vue';
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];
const router = createRouter({
history: createWebHistory(), // 使用 HTML5 History 模式
routes
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3. 路由模式设置
- Vue 2 使用
mode
const router = new VueRouter({
mode: 'hash', // 或 'history'
routes
});
2
3
4
- Vue 3 使用
createWebHistory
const router = createRouter({
history: createWebHistory(), // HTML5 History 模式
routes
});
2
3
4
# 4. 路由信息获取
# Vue 2 获取路由信息
使用 this.$route
和 this.$router
:
this.$route
:获取当前路由信息,如路径、参数等。this.$router
:用于路由操作,如跳转、替换路由等。
// 在组件中
this.$route.path; // 获取当前路由路径
this.$router.push; // 跳转路由
2
3
# Vue 3 获取路由信息
在 Vue 3 中,使用 Composition API
提供的 useRoute
和 useRouter
两个组合式函数来获取路由信息和执行路由操作。
useRoute()
:- 用于获取当前激活的路由对象。
- 返回的对象与 Vue 2 的
this.$route
类似,包含路由的路径、参数等信息。
useRouter()
:- 返回一个路由实例,提供导航功能。
- 类似于 Vue 2 中的
this.$router
,用于跳转路由、替换路由等。
import { useRoute, useRouter } from 'vue-router';
export default {
setup() {
const route = useRoute();
const router = useRouter();
// 获取当前路由信息
console.log('当前路径:', route.path);
// 路由跳转
const goToAbout = () => {
router.push('/about');
};
return { goToAbout };
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 5. 插件使用
在 Vue 2 和 Vue 3 中,路由插件的注册方式有所不同,以下是它们的区别和使用示例:
# Vue 2 路由插件注册
- 注册方式:在
index.js
文件中使用Vue.use(VueRouter)
注册路由插件。 - 典型流程:
- 在
index.js
中创建和配置VueRouter
实例。 - 将
router
实例传递给 Vue 实例。
- 在
示例代码:
// index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import router from './router'; // 导入路由配置
// 注册路由插件
Vue.use(VueRouter);
new Vue({
render: h => h(App),
router, // 使用路由实例
}).$mount('#app');
2
3
4
5
6
7
8
9
10
11
12
13
14
# Vue 3 路由插件注册
- 注册方式:在
main.js
文件中使用app.use(router)
注册路由插件。 - 典型流程:
- 在
main.js
中创建Vue
应用实例。 - 使用
createRouter
创建路由实例。 - 将路由实例注册到应用实例上。
- 在
示例代码:
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router'; // 导入路由配置
// 创建应用实例
const app = createApp(App);
// 注册路由插件
app.use(router);
// 挂载应用
app.mount('#app');
2
3
4
5
6
7
8
9
10
11
12
13
14
- Vue 3:利用
createApp
创建应用实例,并通过app.use()
注册插件,直接在main.js
中进行。这种方式提供了更好的模块化支持,简化了项目结构。
# 6. 组合式 API 支持
Vue 2 不支持组合式 API
需要使用
Options API
进行状态管理和路由操作。Vue 3 支持组合式 API
可以在
setup
中使用组合式 API:import { ref } from 'vue'; import { useRoute } from 'vue-router'; export default { setup() { const route = useRoute(); const currentRoute = ref(route.path); return { currentRoute }; } };
1
2
3
4
5
6
7
8
9
10
11
# 7. 代码分割与懒加载
Vue 2 代码分割
const Foo = () => import('./Foo.vue');
1Vue 3 代码分割
Vue 3 支持
defineAsyncComponent
以更好的方式实现异步组件:import { defineAsyncComponent } from 'vue'; const Foo = defineAsyncComponent(() => import('./Foo.vue') );
1
2
3
4
5
# 8. 动态路由和命名视图支持
Vue 2 动态路由和命名视图
const routes = [ { path: '/user/:id', component: User, props: true } ];
1
2
3Vue 3 动态路由和命名视图
const routes = [ { path: '/user/:id', component: User, props: route => ({ id: route.params.id }) } ];
1
2
3
# 9. 路由守卫与导航钩子
Vue 2 和 Vue 3 中的路由守卫与导航钩子的使用方式基本一致。主要的区别在于 Vue 3 中使用了新的组合式 API 来获取路由实例和路由信息 (使用 useRoute
和 useRouter
。)。在路由守卫的使用和导航钩子的定义上,语法和概念都保持不变。
# 全局守卫
无论是在 Vue 2 还是 Vue 3 中,全局守卫的定义方式是相同的:
beforeEach
: 在每次导航之前执行。afterEach
: 在每次导航之后执行。
Vue 2 和 Vue 3 中的全局前置守卫
// 在 Vue 2 和 Vue 3 中都一样
router.beforeEach((to, from, next) => {
// 这里可以执行一些逻辑
// 比如检查用户是否已登录
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login'); // 重定向到登录页面
} else {
next(); // 放行
}
});
router.afterEach((to, from) => {
// 执行一些后置逻辑
console.log(`导航到: ${to.path}`);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 组件内守卫
组件内守卫在 Vue 2 和 Vue 3 中也保持不变,主要用于在组件的生命周期内进行导航控制:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
Vue 2 和 Vue 3 中的组件内守卫
export default {
// 在路由进入之前执行
beforeRouteEnter(to, from, next) {
// 在组件实例创建之前,这里没有 this
next(vm => {
// 在导航成功后访问组件实例
vm.initialize();
});
},
// 在路由更新时执行
beforeRouteUpdate(to, from, next) {
// 在当前路由改变但是依然在同一个组件实例时被调用
this.someMethod();
next();
},
// 在路由离开之前执行
beforeRouteLeave(to, from, next) {
// 可以用来阻止导航
if (this.hasUnsavedChanges) {
const answer = window.confirm('你有未保存的更改。确定要离开吗?');
if (!answer) next(false);
} else {
next();
}
}
};
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
总结
- 守卫的使用:Vue 2 和 Vue 3 的路由守卫在逻辑和定义方式上基本一致。
- 获取路由信息:Vue 3 提供了
useRoute
和useRouter
组合式 API,用于在setup
中使用。 - 导航控制:依然通过
next
函数进行导航控制,支持重定向、取消导航等操作。
# 10. 对象形式的 props 传参支持
在 Vue 3 中,相较于 Vue 2,props
的传递方式确实更灵活,提供了更强大的功能。这意味着在 Vue 3 中可以更方便地将路由对象的内容传递给组件。
# Vue 2 中 props
传参
在 Vue 2 中,通过设置 props: true
来将动态路由参数(params
)传递给组件。通常是将路径中的动态参数(如 :id
)作为 props
传递给组件。
示例代码
const routes = [
{
path: '/user/:id', // 动态路由参数 :id
component: UserComponent,
props: true // 将 params 中的 id 作为 props 传递
}
];
2
3
4
5
6
7
在这个示例中,id
会作为 props
被传递给 UserComponent
。
# Vue 3 中 props
传参
在 Vue 3 中,除了可以像 Vue 2 一样直接传递动态路由参数之外,还可以使用函数形式更灵活地传递路由对象中的各种信息(例如 query
、params
、hash
、meta
等)给组件。
示例代码
const routes = [
{
path: '/user/:id',
component: UserComponent,
props: (route) => {
return {
id: route.params.id, // 动态路由参数
name: route.query.name, // 查询参数
section: route.hash, // hash 部分
isAuthenticated: route.meta.requiresAuth // 路由元信息
};
}
}
];
2
3
4
5
6
7
8
9
10
11
12
13
14
# 函数形式 props
传递的优势
- 灵活性:函数形式可以根据业务逻辑处理参数,例如格式化或校验后传递。
- 传递多种路由信息:不仅可以传递
params
,还可以传递query
、hash
和meta
等。 - 解耦组件与路由:组件不再需要直接依赖
route
对象,可以通过props
获得所需信息,增加组件的复用性。
# 在组件中使用 props
在组件中可以通过 defineProps
或 props
选项来接收传递过来的 props
,如下所示:
示例代码
<template>
<div>
<h2>用户 ID: {{ id }}</h2>
<h3>用户名称: {{ name }}</h3>
<p>当前部分: {{ section }}</p>
<p>需要认证: {{ isAuthenticated }}</p>
</div>
</template>
<script setup>
export default {
import { defineProps } from 'vue';
// 使用 defineProps 接收传递过来的 props
const props = defineProps(['id', 'name', 'section', 'isAuthenticated']);
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
总结
- Vue 2:主要通过
props: true
传递动态路由参数。 - Vue 3:使用函数形式,可以更灵活地传递路由对象的各种信息,增强组件与路由的解耦性。