各位未来的前端大神们,早上好!我是老码农,今天咱们聊聊 Vue Router 里的两种导航方式,编程式导航和声明式导航。这俩哥们儿,一个动如脱兔,一个静如处子,各有千秋,掌握好了能让你的 Vue 应用流畅丝滑。
开场白:导航的重要性,以及为什么要有两种方式?
想象一下,你正在逛淘宝,如果每次点击链接都要刷新整个页面,那体验简直就是噩梦。Vue Router 的出现就是为了解决这个问题,它让你的 Vue 应用也能拥有单页应用 (SPA) 的丝滑体验,无需刷新页面就能切换不同的视图。
那为什么要有编程式和声明式两种导航方式呢?原因很简单:
- 声明式导航: 简单直接,适合静态链接,比如导航栏里的链接。
- 编程式导航: 灵活强大,适合处理复杂的逻辑,比如表单提交后跳转,或者根据用户权限跳转到不同的页面。
第一部分:声明式导航:简单粗暴,一目了然
声明式导航,顾名思义,就是通过声明的方式来告诉 Vue Router 你想去哪里。最常用的就是 <router-link>
组件。
1. router-link
组件:导航界的扛把子
router-link
组件就像一个披着 <a>
标签外衣的超级英雄,它能帮你轻松实现页面跳转,而且还不会刷新页面。
-
基本用法:
<router-link to="/home">去首页</router-link>
这段代码会在页面上渲染出一个链接,点击后会跳转到
/home
路由。 -
to
属性:to
属性是router-link
最重要的属性,它用来指定你要跳转的路由。to
属性的值可以是:- 字符串: 直接指定路由路径,例如
to="/home"
。 -
对象: 更加灵活,可以传递参数,例如:
<router-link :to="{ path: '/user', query: { id: 123 }}">查看用户详情</router-link>
这段代码会跳转到
/user?id=123
路由。<router-link :to="{ name: 'user', params: { id: 123 }}">查看用户详情</router-link>
这段代码会跳转到 name 为 user 的路由,并传递 id 参数。
- 字符串: 直接指定路由路径,例如
-
replace
属性:默认情况下,
router-link
会使用history.pushState()
方法来跳转页面,这会在浏览器的历史记录中添加一条记录。如果你想使用history.replaceState()
方法来替换当前的记录,可以使用replace
属性。<router-link to="/home" replace>去首页</router-link>
-
active-class
和exact-active-class
属性:这两个属性用来指定链接激活时的 CSS 类名。
active-class
会在链接对应的路由是当前路由的子路由时激活,而exact-active-class
只会在链接对应的路由是当前路由时激活。<router-link to="/home" active-class="active">首页</router-link>
这段代码会在
/home
路由激活时,给链接添加active
类。
2. 声明式导航的优点和缺点:
优点 | 缺点 |
---|---|
简单易用,代码可读性高 | 灵活性较差,无法处理复杂的逻辑 |
适合静态链接,比如导航栏、侧边栏等 | 无法在跳转前进行验证,比如判断用户是否登录 |
性能较好,router-link 组件内部做了优化,避免了不必要的渲染 |
如果需要动态生成链接,或者需要根据条件显示不同的链接,代码会变得比较复杂 |
第二部分:编程式导航:灵活强大,掌控全局
编程式导航,顾名思义,就是通过编写代码的方式来控制 Vue Router 的跳转。它允许你更加灵活地处理各种复杂的场景。
1. $router
对象:导航界的指挥官
在 Vue 组件中,你可以通过 $router
对象来访问 Vue Router 的实例。$router
对象提供了以下几个常用的方法:
-
push(location, onComplete?, onAbort?)
:push
方法用来跳转到指定的路由,它会在浏览器的历史记录中添加一条记录。-
location
参数:location
参数可以是:- 字符串: 直接指定路由路径,例如
this.$router.push('/home')
。 -
对象: 更加灵活,可以传递参数,例如:
this.$router.push({ path: '/user', query: { id: 123 } }); this.$router.push({ name: 'user', params: { id: 123 } });
- 字符串: 直接指定路由路径,例如
-
onComplete
和onAbort
参数:onComplete
和onAbort
是可选的回调函数,分别在跳转成功和跳转失败时执行。this.$router.push( '/home', () => { console.log('跳转成功'); }, () => { console.log('跳转失败'); } );
-
-
replace(location, onComplete?, onAbort?)
:replace
方法和push
方法类似,但是它会替换当前的浏览器历史记录,而不是添加一条新的记录。this.$router.replace('/home');
-
go(n)
:go
方法用来在浏览器的历史记录中前进或后退n
步。// 后退一步 this.$router.go(-1); // 前进一步 this.$router.go(1);
-
back()
:back
方法相当于this.$router.go(-1)
,用来后退一步。this.$router.back();
-
forward()
:forward
方法相当于this.$router.go(1)
,用来前进一步。this.$router.forward();
2. 编程式导航的应用场景:
-
表单提交后跳转:
<template> <form @submit.prevent="handleSubmit"> <input type="text" v-model="username" /> <button type="submit">提交</button> </form> </template> <script> export default { data() { return { username: '', }; }, methods: { handleSubmit() { // 验证表单数据 if (this.username) { // 跳转到用户详情页 this.$router.push({ name: 'user', params: { username: this.username } }); } else { alert('请输入用户名'); } }, }, }; </script>
-
根据用户权限跳转:
<template> <button @click="handleLogin">登录</button> </template> <script> export default { methods: { handleLogin() { // 模拟登录 const isLoggedIn = true; if (isLoggedIn) { // 跳转到首页 this.$router.push('/home'); } else { // 跳转到登录页 this.$router.push('/login'); } }, }, }; </script>
-
处理复杂的路由参数:
<template> <button @click="handleSearch">搜索</button> </template> <script> export default { data() { return { keyword: 'vue', category: 'framework', }; }, methods: { handleSearch() { // 构建复杂的路由参数 const query = { keyword: this.keyword, category: this.category, page: 1, }; // 跳转到搜索结果页 this.$router.push({ path: '/search', query: query }); }, }, }; </script>
3. 编程式导航的优点和缺点:
优点 | 缺点 |
---|---|
灵活性强,可以处理各种复杂的逻辑 | 代码可读性相对较差,需要编写更多的代码 |
可以在跳转前进行验证,比如判断用户是否登录 | 性能相对较差,需要手动控制跳转逻辑 |
可以动态生成链接,或者根据条件显示不同的链接 | 容易出错,需要仔细测试 |
第三部分:声明式导航 vs 编程式导航:如何选择?
既然有两种导航方式,那我们该如何选择呢?
选择依据 | 声明式导航 | 编程式导航 |
---|---|---|
使用场景 | 静态链接,简单的页面跳转 | 复杂的逻辑,需要在跳转前进行验证或处理参数 |
代码量 | 较少 | 较多 |
灵活性 | 较低 | 较高 |
可读性 | 较高 | 较低 |
性能 | 较好 | 相对较差 |
适用性 | 导航栏,侧边栏,简单的列表链接 | 表单提交,用户权限控制,复杂的搜索功能 |
总结:
声明式导航就像是自动挡汽车,简单易用,适合日常驾驶。编程式导航就像是手动挡汽车,需要一定的驾驶技巧,但是可以让你更好地掌控车辆。
在实际开发中,我们通常会将两种导航方式结合起来使用。对于简单的静态链接,可以使用声明式导航;对于复杂的逻辑,可以使用编程式导航。
彩蛋:router.resolve
方法
Vue Router 还提供了一个 router.resolve
方法,它可以将一个 location
对象解析成一个完整的 URL。这个方法在某些场景下非常有用,比如你需要获取一个链接的 URL,但是又不想立即跳转。
const route = this.$router.resolve({ name: 'user', params: { id: 123 } });
console.log(route.href); // 输出:/user/123
结束语:
掌握了声明式导航和编程式导航,你就掌握了 Vue Router 的核心技能。希望今天的讲解对你有所帮助。记住,多写代码,多思考,才能成为真正的前端大神!下次有机会再和大家分享更多前端技术。
祝大家编码愉快!