路由守卫
守卫分为全局守卫,单独路由守卫,组件路由守卫
- 全局前置守卫
const router = new Router
router.beforeEach((to, from, next => {
return false
})
-
to 即将进入的路由目标
-
from 当前路由
-
return false 则终止当前路由
-
return 一个路由地址 表示当前路由被拦截并导向规定的路由地址
-
next (可选) 只能被调用一次,
-
全局解析守卫 每次导航都会触发,但是确保导航被确认前 ,组件守卫和异步路由组件被解析后,解析守卫就会被正确使用。
router.beforeResolve(async to => {
if(to.meta.requireCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
// ... 处理错误,然后取消导航
return false
} else {
// 意料之外的错误,取消导航并把错误传给全局处理器
throw error
}
}
}
})
- 全局后置钩子 在路由完成之后触发,它能够收集to from信息并作出对应的处理
router.afterEach(())
- 路由独享守卫 beforeEnter,只在对应的路由进入时候触发,并且当参数改变时不会重复触发
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]
- 组件内路由守卫
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染该组件的对应路由被验证前调用
// 不能获取组件实例 `this` !
// 因为当守卫执行时,组件实例还没被创建!
},
beforeRouteUpdate(to, from) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
// 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
},
beforeRouteLeave(to, from) {
// 在导航离开渲染该组件的对应路由时调用
// 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
},
}
完整的路由解析流程
- beforeRouterLeave
- beforeEach
- beforeRouterUpdate
- beforeEnter
- 解析异步路由组件
- beforeResolve
- afterEach
路由元
meta 用于标记并添加额外的路由信息
获取数据
应用场景: user路由下获取用户信息并根据这些信息来渲染页面
- 在页面的生命周期内获取数据 并提示‘加载中’
- 在路由导航完成之前,通过路由守卫获取数据,然后将获取的数据传递给导航
// 在路由中获取数据实例
export default {
data() {
return {
post: null,
error: null,
}
},
beforeRouteEnter(to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改变前,组件就已经渲染完了
// 逻辑稍稍不同
async beforeRouteUpdate(to, from) {
this.post = null
try {
this.post = await getPost(to.params.id)
} catch (error) {
this.error = error.toString()
}
},
}
过渡
将组件放在transition 标签中,并根据路由元信息动态设置动画效果
<router-view v-slot="{ Component }">
<transition :name="route.meta.transition || 'fade'">
<component :is="Component" />
</transition>
</router-view>
滚动行为
模拟锚点
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
el: to.hash,
}
}
},
})
延迟滚动
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ left: 0, top: 0 })
}, 500)
})
},
})
动态路由 addRoute removeRoute
查看现有路由
Vue Router 提供了两个功能来查看现有的路由:
- router.hasRoute:检查路由是否存在。
- router.getRoutes:获取一个包含所有路由记录的数组。