Vue.js通过组合组件来组成应用程序,使用 VueRouter将组件映射到路由 (routes),然后告诉 VueRouter 在哪里渲染它们
声明式导航
使用<router-link>组件来导航,通过传入 `to` 属性指定链接,<router-link> 默认会被渲染成一个 `<a>` 标签,可以使用`tag`属性指指定渲染标签
// router-link将被渲染成div
<router-link to="/foo" tag='div'>Go to Foo</router-link>
// 路由匹配到的组件将渲染在router-view组件中
<router-view></router-view>
当前激活的router-link的class中含有.router-link-active,可利用这个class定义激活样式
.router-link-active {
color: red;
}
注入路由
通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由
// 注入路由
const app = new Vue({
router
}).$mount('#app')
// 使用路由器进行路由跳转
this.$router.push('home')
// 访问当前路由参数
this.$route.params.username
动态路由
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
当匹配到一个路由时,参数值会被设置到 this.$route.params。当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用,因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效,这也意味着组件的生命周期钩子不会再被调用(mounted、created等),所以此时不应该在mounted、created阶段获取参数
// 监听路由变化,做出相应的请求操作
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
}
// 监听路由变化,做出相应的请求操作
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// 对路由变化作出响应...
next()
}
}
通配符
{
// 会匹配以 `/user-` 开头的任意路径
path: '/user-*'
}
当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:
// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
嵌套路由
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
},
{
// 空的子路由
// 当 /user/:id/posts 匹配成功
// UserHome 会被渲染在 User 的 <router-view> 中
path: '',
component: UserHome
},
]
}
]
})
编程式导航
// 字符串路径,等同于router.push({ path: 'home' })
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由:需要在路由映射中配置name
routes: [
{ path: '/user', name: 'user', component: User }
]
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
// 如果提供了 path,params 会被忽略,这里的 params 不生效,user页面获取不到params
router.push({ path: '/user', params: { userId }}) // -> /user
守卫导航
- 全局前置守卫
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// 设置title
document.title = to.meta.title !== undefined ? to.meta.title : '默认名'
next()
})
next(): 进行管道中的下一个钩子。
next(false): 中断当前的导航。
- 全局后置钩子
router.afterEach((to, from) => {
// ...
})
- 路由独享的守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
- 组件内的守卫
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
// 不过,你可以通过传一个回调给 next来访问组件实例
next(vm => {
// 通过 `vm` 访问组件实例
})
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
next()
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
// 可以通过next(false)中断退出:弹出提示信息[ 订单未支付 / 表单信息未填写完 ]
next()
}
}