1、动态路由匹配
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
})
现在呢,像 /user/foo
和 /user/bar
都将映射到相同的路由。
当匹配到一个路由时,参数值会被设置到 this.$route.params
,可以在每个组件内使用。于是,我们可以更新 User
的模板,输出当前用户的 ID:
this.$route.params.id
2、响应路由参数的变化
提醒一下,当使用路由参数时,例如从/user/foo导航到/user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化作出响应的话,你可以简单的watch(检测变化)$route对象:
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
console.log(to,from)
}
}
3、嵌套路由
借助 vue-router
,使用嵌套路由配置,就可以很简单地表达这种关系。
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
这里的
是最顶层的出口,渲染最高级路由匹配到的组件。同样地,一个被渲染组件同样可以包含自己的嵌套
。例如,在 User
组件的模板添加一个
:
const User = {
template: `
User {{ $route.params.id }}
`
}
要在嵌套的出口中渲染组件,需要在 VueRouter
的参数中使用 children
配置:
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 中
path: 'posts',
component: UserPosts
}
]
}
]
})
要注意,以 /
开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
你会发现,children
配置就是像 routes
配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
此时,基于上面的配置,当你访问 /user/foo
时,User
的出口是不会渲染任何东西,这是因为没有匹配到合适的子路由。如果你想要渲染点什么,可以提供一个 空的 子路由:
const router = new VueRouter({
routes: [
{
path: '/user/:id', component: User,
children: [
// 当 /user/:id 匹配成功,
// UserHome 会被渲染在 User 的 中
{ path: '', component: UserHome },
// ...其他子路由
]
}
]
})
4、跳转路由,官方叫编程式导航,其实就是跳转路由,及获取参数
router.push()
以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
/ 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 路由是这样的 /user/:id
// 命名的路由 变成 /user/123
router.push({ name: 'user', params: { userId: 123 }})
router.push({ path: '/user/3' })
对应的获取参数:this.$route.params.id
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
参数获取:this.$route.query.plan
//既有动态路由又有查询参数
router.push({path:'/user/3',query:{plan:'c'}})
const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
**这里的 params 不生效**
router.push({ path: '/user', params: { userId }}) // -> /user
下面举个项目经常遇见的例子:
第一种($route获取参数
)经常用
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
要链接到一个命名路由,可以给 router-link 的 to 属性传一个对象:
User
这跟代码调用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 }})
获取参数:
this.$route.params.id
第二种(props获取参数
)
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User,
props: true
}
]
})
方法很多,熟练使用一种就行
router.replace()
跟 router.push
很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
router.go(n)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
5、导航守卫
你可以使用 router.beforeEach
注册一个全局前置守卫:
// 路由守卫
router.beforeEach((to, from, next) => {
// 数据的校验
/*
if(to.fullPath === '/login'){
next()
}else{
next('/login);
// 可以和router里面一样
next({
path:'/login',
})
}
*/
console.log('to', to);
console.log('from', from);
next()
})
在 2.5.0+ 你可以用 router.beforeResolve
注册一个全局守卫。这和 router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
router.beforeResolve((to, from, next) => {
console.log('to', to);
console.log('from', from);
next()
})
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身:
router.afterEach((to, from) => {
console.log('to', to);
console.log('from', from);
})
你可以在路由配置上直接定义 beforeEnter
守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
这些守卫与全局前置守卫的方法参数是一样的。
最后,你可以在路由组件内直接定义以下路由导航守卫:
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
//获取数据 加载数据
next(vm => {
console.log(vm, vm.msg);//在这是拿不到this vm可以 注意
});
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
next();
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
// 切换页面的时候 =》 提醒是否保存已编辑内容
next();
}
}
beforeEach
守卫。beforeRouteUpdate
守卫 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守卫 (2.5+)。afterEach
钩子。beforeRouteEnter
守卫中传给 next
的回调函数。