Vue-router 导航守卫有哪些
Vue Router 提供了几种导航守卫,用于在路由导航过程中进行控制和处理。以下是 Vue Router 的导航守卫:
1. 全局导航守卫
beforeEach(to, from, next)
:在路由发生变化前被调用,可以进行全局的前置处理逻辑。afterEach(to, from)
:在路由变化后被调用,可以进行全局的后置处理逻辑。
2. 路由独享的守卫
beforeEnter(to, from, next)
:在单个路由配置中定义,只会在该路由进入时触发。
3. 组件内的守卫
beforeRouteEnter(to, from, next)
:在目标路由被渲染之前被调用,不能直接访问组件的实例,可以通过传递一个回调给next
方法来访问组件实例。beforeRouteUpdate(to, from, next)
:在当前路由被复用,但传入的路由参数发生变化时被调用,可以访问组件实例且可以调用next
方法。beforeRouteLeave(to, from, next)
:在当前路由将要离开时被调用,可以访问组件实例且可以调用next
方法。
这些导航守卫可以用于实现身份验证、权限控制、路由跳转逻辑等,在路由切换前或切换后进行相关处理。通过在路由配置或组件内使用这些导航守卫,可以控制路由的行为和交互。
Vue-router 路由钩子在生命周期的体现
Vue Router 的导航守卫主要有三种形式:全局守卫、路由独享守卫和组件内守卫。它们在组件生命周期中的体现如下:
-
全局守卫:
-
beforeEach
全局前置守卫在组件被创建之前调用。 -
beforeResolve
全局解析守卫在组件被解析之后调用(2.5.0+)。 -
afterEach
全局后置钩子在组件被销毁之后调用。
全局守卫与组件的生命周期钩子没有直接的关系,它们是在组件生命周期的不同阶段执行的。在全局守卫中,您可以进行一些通用的操作,如登录验证、路由权限检查和页面跳转等。
-
-
路由独享守卫:
-
beforeEnter
路由独享守卫在路由被激活之前调用。
路由独享守卫是应用于单个路由的,它与组件的生命周期钩子在同一个生命周期阶段执行。在路由独享守卫中,您可以执行一些特定于该路由的操作,如加载特定数据或进行权限验证等。
-
-
组件内守卫:
-
beforeRouteEnter
组件内守卫在组件被激活之前调用。 -
beforeRouteUpdate
组件内守卫在当前路由被复用(组件实例被复用)时调用。 -
beforeRouteLeave
组件内守卫在离开当前路由之前调用。
组件内守卫直接关联到组件的生命周期钩子,并在特定的生命周期阶段执行。在组件内守卫中,您可以访问和操作组件的数据,并执行与路由相关的逻辑操作,如数据加载、页面跳转和离开前的数据保存等。
-
总结:
- 全局守卫和路由独享守卫在组件的生命周期之外执行,用于路由级别的操作。
- 组件内守卫与组件的生命周期钩子相关联,用于在特定的生命周期阶段执行与路由相关的操作。
需要注意的是,不同的守卫类型在执行时机上有所不同,您可以根据需求选择合适的守卫类型来处理路由导航过程中的各种逻辑。
全局路由钩子
全局路由钩子是在 Vue Router 中用于在路由导航过程中执行逻辑操作的钩子函数。它们对整个应用程序范围内的路由进行控制和管理。以下是 Vue Router 的三个全局路由钩子:
-
beforeEach
: 全局前置守卫
- 在每次路由切换之前调用。
- 可以用于进行全局的权限验证、登录状态检查等操作。
- 如果需要进行异步操作,可以返回一个 Promise 对象。
示例:
javascript">router.beforeEach((to, from, next) => {
// 进行登录状态检查
if (!isLoggedIn()) {
next('/login'); // 没有登录则跳转到登录页
} else {
next(); // 继续导航
}
});
-
beforeResolve
: 全局解析守卫
- 在路由解析之后(包括组件异步加载)调用,即在导航被确认之前调用。
- 与
beforeEach
类似,但在解析异步路由组件时更有用。
示例:
router.beforeResolve((to, from, next) => {
// 加载异步数据
fetchData().then(() => {
next();
});
});
-
afterEach
: 全局后置钩子
- 在每次路由切换之后调用。
- 可以用于进行一些全局的清理操作,例如滚动条位置重置或页面切换动画等。
示例:
router.afterEach((to, from) => {
// 重置滚动条位置
window.scrollTo(0, 0);
});
这些全局路由钩子使您可以控制整个应用程序的路由导航过程,执行特定的逻辑操作,如权限验证、数据加载和页面切换动画等。请注意,如果全局前置守卫中未调用 next()
方法,路由将被中断,并且不会导航到目标路由。
单个路由独享钩子
单个路由独享钩子是在 Vue Router 中用于对某个特定路由进行独立配置的钩子函数。它们只会在指定的路由上触发,而不会应用于其他路由。以下是 Vue Router 中的两个单个路由独享钩子:
-
beforeEnter
:路由独享的守卫钩子
- 在特定路由配置对象中定义,仅应用于该路由。
- 在路由被激活之前调用,可以用于进行特定路由的权限验证、数据加载等操作。
示例:
const router = new VueRouter({
routes: [
{
path: '/admin',
***ponent: Admin,
beforeEnter: (to, from, next) => {
// 仅在管理员角色下才能访问
if (isAdmin()) {
next();
} else {
next('/login');
}
}
}
]
});
-
beforeRouteLeave
:组件内路由守卫
- 在组件内部定义,用于在当前路由离开时执行操作。
- 在组件实例销毁之前调用,可以用于执行一些离开前的数据保存、用户确认等操作。
示例:
const Foo = {
template: `<div>Foo</div>`,
beforeRouteLeave(to, from, next) {
// 提示用户确认离开
if (confirm('确定要离开吗?')) {
next();
} else {
next(false); // 取消离开
}
}
};
单个路由独享钩子使您能够在特定路由上完成额外的配置和操作,与全局路由钩子和组件内钩子一起,帮助您更好地控制和管理应用程序的路由行为。请注意,如果在路由独享的守卫中未调用 next()
方法,路由将被中断,并且不会导航到目标路由。
组件内钩子
在 Vue Router 中,组件内钩子是在组件级别定义的用于处理路由导航过程的钩子函数。这些钩子函数与组件生命周期钩子密切相关,用于在特定组件内执行与路由相关的操作。以下是 Vue Router 中常用的组件内钩子:
-
beforeRouteEnter
:进入路由前的守卫
- 在路由激活之前调用。
- 无法访问组件实例
this
,但可以通过传入to, from, next
参数访问。- 通常用于在路由激活之前获取数据或执行一些准备工作。
示例:
beforeRouteEnter (to, from, next) {
fetchData().then((data) => {
next(vm => {
vm.data = data;
});
});
}
-
beforeRouteUpdate
:路由更新前的守卫
- 在当前路由改变,但是该组件被复用时调用。
- 可以通过导航的
to
和from
访问更新前后的路由状态。
示例:
beforeRouteUpdate (to, from, next) {
updateData();
next();
}
-
beforeRouteLeave
:离开路由前的守卫
- 在路由离开当前组件之前调用。
- 可以用于执行一些离开前的操作,如数据保存、确认等。
示例:
beforeRouteLeave (to, from, next) {
if (confirm('确定要离开吗?')) {
next();
} else {
next(false);
}
组件内钩子与全局路由钩子和路由独享守卫的区别在于它们是直接定义在组件内部的,只在特定组件生命周期中执行。通过组件内钩子,您可以针对特定组件的路由导航过程执行个性化的操作,例如加载数据、更新状态和确认操作等。这些钩子函数帮助您更好地组织和控制组件与路由之间的交互行为。
路由导航解析流程
路由导航解析流程描述了在 Vue Router 中进行路由切换时各个守卫和钩子函数的触发顺序。下面是完整的路由导航解析流程(不包括其他生命周期):
- 触发进入其他路由。
- 调用将要离开的路由组件中的
beforeRouteLeave
守卫。- 调用全局前置守卫
beforeEach
。- 在重用的组件中调用
beforeRouteUpdate
守卫。- 调用路由独享守卫
beforeEnter
。- 解析异步路由组件(如果有)。
- 在将要进入的路由组件中调用
beforeRouteEnter
守卫。- 调用全局解析守卫
beforeResolve
。- 导航被确认。
- 调用全局后置钩子的
afterEach
钩子。- 触发 DOM 更新(
mounted
)。- 执行
beforeRouteEnter
守卫中传递给next
的回调函数。
这个流程展示了在进行路由切换时各个守卫和钩子函数的执行顺序。
触发钩子的顺序
在 Vue Router 中,路由导航、keep-alive 和组件生命周期钩子结合在一起时,它们的触发顺序如下,假设是从组件 A 离开,第一次进入组件 B:
beforeRouteLeave
:路由组件的组件离开路由前钩子,可用于执行离开前的操作,例如数据保存或用户确认。beforeEach
:路由全局前置守卫,可用于登录验证、全局路由 loading 等。beforeEnter
:路由独享守卫。beforeRouteEnter
:路由组件的组件进入路由前钩子。beforeResolve
:路由全局解析守卫。afterEach
:路由全局后置钩子。beforeCreate
:组件生命周期钩子,在此阶段无法访问this
。created
:组件生命周期钩子,在此阶段可以访问this
,但无法访问 DOM。beforeMount
:组件生命周期钩子。deactivated
:离开缓存组件 A,或者触发 A 的beforeDestroy
和destroyed
组件销毁钩子。mounted
:访问/操作 DOM。activated
:进入缓存组件,也可能进入 A 的嵌套子组件(如果有的话)。- 执行
beforeRouteEnter
回调函数中传递的next
。
这个触发顺序描述了在路由切换过程中,以及组件生命周期钩子与路由守卫相结合时的执行顺序。
导航行为被触发到导航完成的整个过程
导航行为被触发到导航完成的整个过程描述了在 Vue Router 中进行路由切换时各个阶段的处理过程。下面是这个过程的具体步骤:
- 导航行为被触发,此时导航未被确认。
- 在失活的组件里调用离开守卫
beforeRouteLeave
。- 调用全局的
beforeEach
守卫。- 在重用的组件里调用
beforeRouteUpdate
守卫(如果有)。- 在路由配置里调用
beforeEnter
。- 解析异步路由组件(如果有)。
- 在被激活的组件里调用
beforeRouteEnter
。- 调用全局的
beforeResolve
守卫(如果有),标识解析阶段完成。- 导航被确认。
- 调用全局的
afterEach
钩子。- 非重用组件,开始组件实例的生命周期:
beforeCreate
&created
、beforeMount
&mounted
。- 触发 DOM 更新。
- 用创建好的实例调用
beforeRouteEnter
守卫中传递给next
的回调函数。- 导航完成。
这个过程详细描述了在进行路由切换时各个阶段的处理情况,包括路由守卫、组件生命周期钩子以及导航确认的过程。
Vue-router跳转和location.href有什么区别
当涉及到页面跳转时,Vue Router 和使用 location.href
有一些重要的区别:
1. 使用 location.href
进行跳转
- 当您使用
location.href = '/url'
时,实际上是在浏览器中创建了一个新的页面请求,这会导致整个页面被重新加载。- 页面的重新加载意味着浏览器会重新请求页面所需的所有资源,重新执行页面的生命周期钩子,并重新渲染整个页面。这可能会带来性能上的开销,并且会导致用户在页面切换时看到页面的闪烁或白屏现象。
2. 使用 Vue Router 进行跳转
- Vue Router 是专门为单页面应用 (SPA) 设计的路由管理器。通过使用 Vue Router,您可以在不刷新整个页面的情况下实现页面之间的切换。
- 当您使用 Vue Router 进行路由跳转时(比如使用
router.push('/url')
),Vue Router 会利用浏览器的 history API(包括history.pushState
)来实现页面的切换,而不会导致整个页面的重新加载。- Vue Router 的跳转是通过 JavaScript 来操作路由,实现了前端路由的无刷新跳转,从而提高了用户体验和性能。同时,Vue Router 还使用了 diff
算法来按需加载页面组件,从而减少了对 DOM 的消耗。
总体来说,使用 Vue Router 进行页面跳转可以让您在单页面应用中实现流畅的页面切换,而不会导致整个页面的重新加载。这种方式提供了更好的用户体验,并有助于提升应用的性能。
持续学习总结记录中,回顾一下上面的内容:
Vue Router 中的导航守卫包括beforeEach
、beforeResolve
、afterEach
和路由独享守卫beforeEnter
。这些守卫允许您在路由切换前、解析完成后和路由切换后执行自定义逻辑,比如权限验证、全局加载状态等。
Vue Router 的路由钩子在组件生命周期中的体现主要是通过beforeRouteEnter
、beforeRouteUpdate
和beforeRouteLeave
这三个钩子函数来实现的,它们分别对应着组件的进入、更新和离开时的操作。
在路由跳转方面,使用 Vue Router 进行跳转可以在单页面应用中实现无刷新的页面切换,提供更好的用户体验和性能。相比之下,使用location.href
进行跳转会导致整个页面的重新加载,包括重新请求页面所需的资源、重新执行页面的生命周期钩子和重新渲染页面,可能会影响用户体验和性能。Vue Router 的跳转是通过 JavaScript 来操作路由,利用浏览器的 history API 实现无刷新的页面切换,从而提高用户体验和性能。