1.编程式的导航
router.push(location, onComplete?, onAbort?)
向history栈中添加一个记录,点击回退可回到之前的url
在Vue实例内部,可以通过 $router 访问路由实例。因此可以调用 this.$router.push。
用法
| 声明式 | 编程式 |
|---|---|
<router-link :to="..."> |
router.push(...) |
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意点:
问题1:使用 path和params进行传递参数 将导致无效,
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
解决方案1:
你需要提供路由的 name 或手写完整的带有参数的 path:
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
问题2:路由地址只有参数变化将不会响应变化
如果目的地和当前路由相同,只有参数发生了改变,数据将不会得到更新 (比如从一个用户资料到另一个 /users/1 -> /users/2)
原因:两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
解决方案2:
1.需要使用 beforeRouteUpdate 来响应这个变化
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
2.使用watch对路由$route对象进行监听
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
}
导航守卫
全局前置守卫
发生时间:守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中
router.beforeEach((to,from,next)=>{.....})
next()必须调用,否则无法钩子函数不会进入resolved
全局解析守卫(2.5.0新增)
发生时间:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
router.beforeResolve((to,from,next)=>{.....})
全局后置钩子
不会接受next函数也不会改变导航本身
router.afterEach((to,from)=>{.....})
路由独享守卫
在路由配置中直接定义
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
组件内的守卫
beforeRouteEnterbeforeRouteUpdate(2.2 新增)beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
// 不过可以传一个回调给next来访问组件实例,如下
next(vm=>{
// 通过 `vm` 访问组件实例
})
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
this.name = to.params.name
next()
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。
beforeRouteLeave (to, from , next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
完整的导航解析流程
- 1.导航被触发。
- 2.在失活的组件里调用离开守卫。
- 3.调用全局的
beforeEach守卫。 - 4.在重用的组件里调用
beforeRouteUpdate守卫 (2.2+)。 - 5.在路由配置里调用
beforeEnter。 - 6.解析异步路由组件。
- 7.在被激活的组件里调用
beforeRouteEnter。 - 8.调用全局的
beforeResolve守卫 (2.5+)。 - 9.导航被确认。
- 10.调用全局的
afterEach钩子。 - 11.触发 DOM 更新。
- 12.用创建好的实例调用
beforeRouteEnter守卫中传给next的回调函数。