整理目的:
- 了解 VueRouter 的特性。
- 了解 VueRouter 的使用方法。
- 了解 VueRouter 的实现思路。
- 了解 VueRouter 的核心概念。
VueRouter 的特性
VueRouter 的目的是为了完善 Vue 单页面应用生态的实现。
其主要功能特性为:
- 嵌套路由/视图表
- 模跨化的、基于组件的路由配置
- 过渡动画
- history/hash 模式
- 自定义滚动条行为
后续需要重点整理基于这些特性的源码实现思路。
VueRouter 的使用方法
VueRouter 的使用包括以下几个方面:
- route 导航配置
- 路由传参
- 导航跳转
- 导航守卫
- 路由模式配置
- 嵌套命名视图
route 导航配置&传参
添加 route 有两种方式:1. 在 Router 对象初始化时设置 routes。2, 后续通过 router.addRoutes 动态添加。
一个 route 包含以下要素:path
、name
、props
、component
、meta
、children
、redirect
、alias
。
通过 children
可以实现路由嵌套。
通过 path
、props
配置可以实现路由传参。
{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
使用函数模式的 props
可以将静态值与基于路由的值结合等等。
{ path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
components
不仅可以展示一个视图,也可以展示多个视图即嵌套命名视图:
<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>
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
通过 redirect
可以实现路由的重定向:
{ path: '/a', redirect: { name: 'foo' }}
要注意区分重定向和重命名的区别:
**/a**
的别名是 **/b**
,意味着,当用户访问 **/b**
时,URL 会保持为 **/b**
,但是路由匹配则为 **/a**
,就像用户访问 **/a**
一样。
{ path: '/a', component: A, alias: '/b' }
导航守卫
VueRouter 的导航守卫分为全局导航守卫、路由独享守卫、组件内的守卫。
全局导航守卫
全局导航守卫通常用于登录验证以及权限验证,在使用中要注意调用顺序和 next
函数的用法。
router.beforeEach((to, from, next)=>{next()})
**next()**
:进行管道中的下一个钩子。**next(false)**
: 中断当前的导航。如果浏览器的 URL 改变了,那么 URL 地址会重置到from
路由对应的地址。**next('/')**
或者**next({ path: '/' })**
: 跳转到一个不同的地址。**next(error)**
: (2.4.0+) 如果传入next
的参数是一个Error
实例,则导航会被终止且该错误会被传递给[router.onError()](https://router.vuejs.org/zh/api/#router-onerror)
注册过的回调。
router.afterEach((to, from) => {})
- `router.beforeResolve((to, from, next)=>{next()})``:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
用例如下:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
路由独享守卫
在路由配置中直接定义beforeEnter
守卫:
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
组件内的导航
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
导航守卫调用顺序
动效
路由切换的动效提供了两种方式:全部路由动效的配置和单个路由动效的配置。这些其实还是对 transition
动效组件的不同应用。具体写法如下:
<transition :name="transitionName">
<router-view></router-view>
</transition>
const Bar = {
template: `
<transition name="fade">
<div class="bar">...</div>
</transition>
`
}
滚动行为
使用 scrollBehavior
方法来保持滚动位置。
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 期望滚动到哪个的位置
//return { x: 0, y: 0 }
//return savedPosition
//return {selector: to.hash}
}
})
具体来说可以实现滚动到指定位置、滚动到指定锚点,并且支持 Promise 返回值。