在上一章的学习中,经过举例说明,咱们了解了 Vue Router 中命名路由、命名视图的使用方法,以及如何经过 query 查询参数传参,或者是采用 param 传参的方式实现路由间的参数传递。经过学习咱们能够发现,在实现路由间的参数传递时,咱们将 Vue Router 与咱们的组件强耦合在一块儿,这无疑是不合适的,那么本章咱们就来学习,如何实现组件和 Vue Router 之间的解耦。javascript
仓储地址:Chapter02-Bronze Decouple Component from Routerhtml
1、 编程式导航前端
在使用 Vue Router 的时候,咱们一般会经过 router-link 标签去生成跳转到指定路由的连接,可是在实际的前端开发中,咱们更多的是经过 js 的方式进行跳转。就像咱们很常见的一个交互需求,用户提交表单,提交成功后跳转到上一页面,提交失败则留在当前页。这时候若是咱们仍是经过 router-link 标签进行跳转就不合适了,咱们须要经过 js 根据表单返回的状态进行动态的判断。vue
在使用 Vue Router 时,咱们已经将 Vue Router 的实例挂载到了 Vue 实例上,所以咱们就能够借助 $router 的实例方法,经过编写 js 代码的方式实现路由间的跳转,而这种方式就是一种编程式的路由导航。java
在 Vue Router 中具备三种导航方法,分别为 push、replace 和 go。咱们最多见的经过在页面上设置 router-link 标签进行路由地址间的跳转,就等同于执行了一次 push 方法。git
在这一小节的示例中,我将使用编程式导航实现经过点击不一样的按钮实现路由间的跳转,最终实现的示意图以下所示。 程序员
而 Vue Router 所提供的 push、replace 和 go 方法则彻底能够对应到浏览器 history api 中所提供的 history.pushState、history.replaceState 和 history.go 方法。github
一、 pushvue-router
当咱们须要跳转新页面时,咱们就能够经过 push 方法将一条新的路由记录添加到浏览器的 history 栈中,经过 history 的自身特性,从而驱使浏览器进行页面的跳转。同时,由于在 history 会话历史中会一直保留着这个路由信息,因此当咱们后退时仍是能够退回到当前的页面。编程
在 push 方法中,参数能够是一个字符串路径,或者是一个描述地址的对象,这里其实就等同于咱们调用了 history.pushState 方法。
// 字符串 => /first
this.$router.push('first')
// 对象 => /first
this.$router.push({ path: 'first' })
// 带查询参数 => /first?abc=123
this.$router.push({ path: 'first', query: { abc: '123' }})
复制代码
const userId = '123'
// 使用命名路由 => /user/123
this.$router.push({ name: 'user', params: { userId }})
// 使用带有参数的全路径 => /user/123
this.$router.push({ path: `/user/${userId}` })
// 这里的 params 不生效 => /user
this.$router.push({ path: '/user', params: { userId }})
复制代码
二、 go
当咱们使用 go 方法时,咱们就能够在 history 记录中向前或者后退多少步,也就是说经过 go 方法你能够在已经存储的 history 路由历史中来回跳。
// 在浏览器记录中前进一步,等同于 history.forward()
this.$router.go(1)
// 后退一步记录,等同于 history.back()
this.$router.go(-1)
// 前进 3 步记录
this.$router.go(3)
// 若是 history 记录不够用,那就默默地失败呗
this.$router.go(-100)
this.$router.go(100)
复制代码
三、 replace
replace 方法一样能够达到实现路由跳转的目的,不过,从名字中你也能够看出,与使用 push 方法跳转不一样是,当咱们使用 replace 方法时,并不会往 history 栈中新增一条新的记录,而是会替换掉当前的记录,所以,你没法经过后退按钮再回到被替换前的页面。
this.$router.replace({
path: '/special'
})
复制代码
经过编程式路由实现路由间切换的示例代码以下所示,你能够本身尝试一下,去熟悉如何经过 js 来实现路由地址间的切换。
<div id="app">
<div class="main">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button type="button" class="btn btn-secondary" @click="goFirst">第一页</button>
<button type="button" class="btn btn-secondary" @click="goSecond">第二页</button>
<button type="button" class="btn btn-secondary" @click="goThird">第三页</button>
<button type="button" class="btn btn-secondary" @click="goFourth">第四页</button>
</div>
<div class="btn-group mr-2" role="group" aria-label="Second group">
<button type="button" class="btn btn-secondary" @click="pre">后退</button>
<button type="button" class="btn btn-secondary" @click="next">前进</button>
</div>
<div class="btn-group mr-2" role="group" aria-label="Third group">
<button type="button" class="btn btn-secondary" @click="replace">替换当前页为特殊页</button>
</div>
</div>
<router-view></router-view>
</div>
</div>
<script> const first = { template: '<h3>当前是第一页</h3>' } const second = { template: '<h3>当前是第二页</h3>' } const third = { template: '<h3>当前是第三页</h3>' } const fourth = { template: '<h3>当前是第四页</h3>' } const special = { template: '<h3>特殊页面</h3>' } const router = new VueRouter({ routes: [{ path: '/first', component: first }, { path: '/second', component: second }, { path: '/third', component: third }, { path: '/fourth', component: fourth }, { path: '/special', component: special }] }) const vm = new Vue({ el: '#app', data: {}, methods: { goFirst() { this.$router.push({ path: '/first' }) }, goSecond() { this.$router.push({ path: '/second' }) }, goThird() { this.$router.push({ path: '/third' }) }, goFourth() { this.$router.push({ path: '/fourth' }) }, next() { this.$router.go(1) }, pre() { this.$router.go(-1) }, replace() { this.$router.replace({ path: '/special' }) } }, router: router }) </script>
复制代码
2、 解耦
在文章开头咱们有提到过,在使用路由传参的时候,咱们将组件与 Vue Router 强绑定在了一块,这意味着在任何须要获取路由参数的地方,咱们都须要加载 Vue Router。那么,如何解决这一强绑定呢?
在以前学习组件相关的知识时,咱们提到了能够经过组件的 props 选项来实现子组件接收父组件传递的值。而在 Vue Router 中,一样给咱们提供了经过使用组件的 props 选项来进行解耦的功能。
在下面的示例中,在定义路由模板时,咱们经过指定须要传递的参数为 props 选项中的一个数据项,以后,咱们经过在定义路由规则时,指定 props 属性为 true,便可实现对于组件以及 Vue Router 之间的解耦。
<script>
const second = {
props: ['id'],
template: '<h3>当前是第二页 --- {{id}} </h3>'
}
const router = new VueRouter({
routes: [{
path: '/second/:id',
component: second,
props: true
}]
})
const vm = new Vue({
el: '#app',
data: {},
methods: {
goSecond() {
this.$router.push({
path: '/second'
})
}
},
router: router
})
</script>
复制代码
针对定义路由规则时,指定 props 属性为 true 这一种状况,在 Vue Router 中,咱们还能够给路由规则的 props 属性定义成一个对象或是函数。不过,若是定义成对象或是函数,此时并不能实现对于组件以及 Vue Router 间的解耦。
在将路由规则的 props 定义成对象后,此时无论路由参数中传递是任何值,最终获取到的都是对象中的值。同时,须要注意的是,props 中的属性值必须是静态的,也就是说,你不能采用相似于子组件同步获取父组件传递的值做为 props 中的属性值。
<script>
const third = {
props: ['name'],
template: '<h3>当前是第三页 --- {{name}} </h3>'
}
const router = new VueRouter({
routes: [{
path: '/third/:name',
component: third,
props: {
name: 'zhangsan'
}
}]
})
const vm = new Vue({
el: '#app',
data: {},
methods: {
goThird() {
this.$router.push({
path: '/third'
})
}
},
router: router
})
</script>
复制代码
<script>
const fourth = {
props: ['id', 'name'],
template: '<h3>当前是第四页 --- {{id}} --- {{name}} </h3>'
}
const router = new VueRouter({
routes: [{
path: '/fourth',
component: fourth,
props: (route) => ({
id: route.query.id,
name: 'zhangsan'
})
}]
})
const vm = new Vue({
el: '#app',
data: {},
methods: {
goFourth() {
this.$router.push({
path: '/fourth'
})
}
},
router: router
})
</script>
复制代码
这一章主要学习了如何经过使用 Vue Router 的实例方法,从而实现编程式导航,以及如何实现组件与 Vue Router 之间的解耦。至此,Vue Router 的一些基础使用方法也就大概介绍完了,其它的知识点将在后面的项目中具体使用到的时候再进行介绍,欢迎持续关注哈~~~
占坑
做者:墨墨墨墨小宇
我的简介:96年生人,出生于安徽某四线城市,毕业于Top 10000000 院校。.NET程序员,枪手死忠,喵星人。于2016年12月开始.NET程序员生涯,微软.NET技术的坚决坚持者,立志成为云养猫的少年中面向谷歌编程最厉害的.NET程序员。
我的博客:yuiter.com
博客园博客:www.cnblogs.com/danvic712