【Vue Router 基础】
用途:创建单页面应用
访问路由器:
通过注入路由器,我们可以在任何组件内通过 this.$router
访问路由器,也可以通过 this.$route
访问当前路由
当 <router-link>
对应的路由匹配成功,将自动设置 class
属性值 .router-link-active
。
动态路由匹配:
一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params
,可以在每个组件内使用。
可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params
中。
注意:提醒一下,当使用路由参数时,例如从
/user/foo
导航到
/user/bar
,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。复用组件时,想对路由参数的变化作出响应的话,你可以简单地
watch
(监测变化)$route
对象
或者使用 2.2 中引入的beforeRouteUpdate
导航守卫
含有通配符的路由应该放在最后。
当使用一个通配符时,$route.params
内会自动添加一个名为 pathMatch
参数。它包含了 URL 通过通配符被匹配的部分
支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。
匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。即从上至下进行匹配。
嵌套路由
要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children
配置
要注意,以 /
开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
编程式的导航
声明式
<router-link :to="...">
编程式
router.push(...)
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
//如果提供了path ,params属性会被忽略
//同样的规则也适用于 router-link 组件的 to 属性。
router.push({ path: 'register', query: { plan: 'private' }})
命名路由
创建 Router 实例的时候,在 routes
配置中给某个路由添加name
属性以设置名称
命名视图
一个页面上需要同时展示多个路由出口。
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components
配置 (带上 s)
重定向和别名
“重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b 使用redirect
来设置路由的重定向
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。使用alias
为路由设置别名
路由组件传参
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
通过 props 解耦:
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true },
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
布尔模式:
如果 props 被设置为 true,route.params 将会被设置为组件属性。
对象模式:
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
HTML5 History 模式
vue-router 默认 hash
模式 —— 使用 URL 的 hash
来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
【Vue Router 进阶】
导航守卫
参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route
对象来应对这些变化,或使用 beforeRouteUpdate
的组件内守卫。
全局前置守卫
确保要调用 next
方法,否则钩子就不会被 resolved。
全局解析守卫
和 router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
全局后置钩子
不会改变导航本身
路由独享的守卫
在路由配置上直接定义 beforeEnter
守卫
组件内的守卫
可以在路由组件内直接定义以下路由导航守卫:
- beforeRouteEnter
- beforeRouteUpdate (2.2 新增)
- beforeRouteLeave
注意 beforeRouteEnter
是支持给 next
传递回调的唯一守卫。对于 beforeRouteUpdate
和 beforeRouteLeave
来说,this 已经可用了(组件已经被创建了),所以不支持传递回调,因为没有必要了。
beforeRouteLeave
离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false)
来取消。
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用离开守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
路由元信息
定义路由的时候可以配置 meta
字段
一个路由匹配到的所有路由记录会暴露为 $route
对象 (还有在导航守卫中的路由对象) 的 $route.matched
数组。因此,我们需要遍历 $route.matched
来检查路由记录中的 meta
字段。
过渡动效
<router-view>
是基本的动态组件,所以我们可以用 <transition>
组件给所有路由设置一样的过渡效果,如果你想让每个路由组件有各自的过渡效果,可以在各路由组件内使用 <transition>
并设置不同的 name
。
数据获取
有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:
- 导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
- 导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。
滚动行为
注意: 这个功能只在支持
history.pushState
的浏览器中可用
当创建一个 Router 实例,你可以提供一个 scrollBehavior
方法
异步滚动
你也可以返回一个 Promise
来得出预期的位置描述
路由懒加载
const Foo = () => import('./Foo.vue')
在路由配置中什么都不需要改变,只需要像往常一样使用 Foo:
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})