一、动态路由匹配
动态路由匹配指的是把某种模式的路由,全都映射到同一组件。
const User = { template: ‘<div>User</div>‘ } const router = new VueRouter({ routes: [{ //动态路径参数,以:开头 {path: ‘/user/:id‘, component: User} }] })
一个路径参数使用:标记。但匹配到一个路由时,参数值会被设置到this.$route.params,可以在每个组件内使用。我们可以更新User的模板,输出当前用户的ID:
const User = { template: ‘<div>User {{ $route.params.id }}</div> }
在一个路由中可以设置多段路径参数,对应的值都会设置到$route.params里。
1 响应路由参数的变化
复用组件时,想对路由参数做出响应的话,你可以简单地watch(检测变化)$route对象。
const User = { template: ‘...‘, watch: { ‘$route‘ (to, from) { // 对路由变化做出响应... } } }
2 高级匹配模式
Vue-router使用path-to-regexp作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。
3 匹配优先级
嵌套路由配置,可以表达URL中各段动态路径也按某种结构对应嵌套的各层组件。
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‘, components: UserPosts } ] } ] })
二、编程式导航
我们可以借助router的方法,通过编写代码来实现router.push(location),这个方法会向history栈中添加一个新记录。
声明式:
<router-link :to="">
编程式:
router.push(...)
替换掉当前的history记录的方法。
声明式:
<router-link :to="..." replace>
编程式:
router.replace(...)
router.go(n)
三、命名视图
同级展示多个视图。可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果router-view没有设置名字,那么默认为default。
<router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view>
const router = new VueRouter({
routes: [
{
path: ‘/‘,
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
四、重定向和别名
1 重定向
const router = new VueRouter({ routes: [ { path: ‘/a‘, redirect: ‘/b‘ } ] })
重定向的目标也可以是一个命名的路由:
const router = new VueRouter({ routes: [ { path: ‘/a‘, redirect: { name: ‘foo‘ }} ] })
甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({ routes: [ { path: ‘/a‘, redirect: to => { // 方法接收目标路由作为参数 // reture 重定向的字符串路径/路径对象 } ] })
2 别名
别名的意思就是,/a的别名是/b,意味着,当用户访问/b时,URL会保持为/b,但是路由匹配则为/a,就像用户访问/a一样。
const router = new VueRouter({ routes: [ { path: ‘/a‘, component: A, alias: ‘/b‘ } ] })
五、导航钩子
Vue-router提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的、单个路由独享的,或者组件级的。
1 全局钩子
你可以使用router.beforeEach注册一个全局的before钩子。
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }
当一个导航触发时,全局的before钩子按照创建顺序调用。钩子是异步解析执行,此时导航在所有钩子resolve完之前一直处于等待中。每个钩子方法接受三个参数:
- to: Route:即将要进入的目标,路由对象。
- from: Route:当导航正要离开的路由。
- next: Function:一定要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参数。
next():进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed(确认的)。
next(false):中断当前的导航。如果浏览器的URL改变了(可能是用户手动或者浏览器后退按钮),那么URL地址会重置到from路由对应的地址。
next(‘/‘)或者next({ path: ‘/‘ }):跳转到一个不同的地址。当前的导航中断,然后进行一个新的导航。
确保要调用next方法,否则钩子就不会被resolved。同样可以主次一个全局的after钩子,不过它不像before钩子那样,after钩子没有next方法,不能改变导航。
router.afterEach(router => { // ... })
2 某个路由独享的钩子
const router = new VueRouter({ routes: [ { path: ‘/foo‘, component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
3 组件内的钩子
你可以直接在路由组件内直接定义一下钩子:
beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被confirm前调用 // 不能获取组件示例`this` // 因为当钩子执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径/foo/:id,在/foo/1和/foo/2之间跳转的时候, // 由于会渲染同样的Foo组件,因此组件示例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例`this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例`this` } }