1、导航被触发
2、在失活的组件里调用 beforeRouteLeave 守卫
组件内守卫beforeRouteLeave
:在离开该组件之前,会先调用它(用于在离开组件前保存或清理一些状态)
import { onBeforeRouteLeave } from 'vue-router'
onBeforeRouteLeave((to, from, next) => {
console.log('to=', to)
console.log('from=', from)
* 如果需要,你可以基于条件阻止导航
if (/* some condition */) {
next(false) // 取消导航
} else {
next() // 允许导航
}
* 默认情况下,调用 next() 允许导航继续
next(false)
})
3、调用全局的 beforeEach 守卫
全局的前置守卫beforeEach
:它会在路由改变之前被调用,用于执行一些全局的权限检查、重定向等逻辑
4、在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)
组件内守卫beforeRouteUpdate
:当路由改变,但是该组件被复用时(例如,只是路由参数改变)
这个守卫,允许,你在组件复用时执行一些逻辑,比如更新DOM。
const userId = ref(null)
const route = useRoute()
setup() {
onBeforeRouteUpdate((to, from, next) => {
* 根据新的路由参数,来更新组件的数据
userId.value = to.params.id // 假设,路由参数中有一个id
next()
})
// 初始化userId(可选,取决于你的具体需求)
if (route.params.id) {
userId.value = route.params.id
}
}
5、在路由配置里调用 beforeEnter
6、解析异步路由组件
7、在被激活的组件里调用 beforeRouteEnter
在进入目标路由的组件之前,会调用 beforeRouteEnter 守卫,
注意:
因为,这个守卫,在导航被确认之前调用,
所以,此时的组件实例,还没有被创建,
因此,你不能直接访问组件实例,但是,你可以通过 next 回调来访问组件实例。
setup() {
const someData = ref(null)
注意:
'onBeforeRouteEnter' 不能在 'setup' 中直接使用,
因此,我们需要将它作为一个单独的函数,定义在组件外部
const beforeRouteEnterGuard = (to, from, next) => {
* 这里没有组件实例,因为,组件还没有被创建,但是,你可以访问路由参数和查询
console.log('在组件被创建之前,即将进入路由', to.path)
* 可以在这里执行一些异步操作,比如:从服务器获取数据
next(vm => {
*通过 `vm` 访问组件实例
})
}
* 在组件外部,定义 'onBeforeRouteEnter' 守卫
onBeforeRouteEnter(beforeRouteEnterGuard)
onMounted(() => {
console.log('组件已挂载')
})
}
8、调用全局的 beforeResolve 守卫(2.5+)
它在,所有组件内守卫
和 异步路由组件被解析之后,但在DOM更新之前被调用
(此时,DOM未更新,所以不能直接操作DOM),
意味着,在 beforeResolve 守卫中,可以进行那些依赖于异步解析的数据的操作,
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/async',
name: 'Async',
component: () => import('./views/AsyncComponent.vue')
}
// ...
]
const router = createRouter({
history: createWebHistory(),
routes,
})
* 使用 beforeResolve 守卫
router.beforeResolve(async (to, from, next) => {
* 假设,我们需要根据路由的某些参数,来加载一些数据
if (to.path === '/async') {
try {
* 异步获取一些数据
const data = await fetchSomeData(to.query.id) * 假设,fetchSomeData是一个返回Promise的函数
* 你可以将数据存储在:Vuex、localStorage、sessionStorage
console.log('Loaded data for route=', data)
* 确保导航继续
next()
} catch (error) {
* 如果加载数据失败,可以重定向到错误页面,或执行其他逻辑
console.error('Failed to load data:', error)
next(false) // 中断导航
// 或者你可以重定向到另一个路由
// next('/error-page')
}
} else {
* 对于其他路由,直接继续
next()
}
})
9、导航被确认
此时,路由已经确定,并准备进行导航
10、调用全局的 afterEach 钩子
无论导航是否成功,都会调用 afterEach 钩子,
这个守卫不接受 next 函数,因为,它发生在所有导航守卫之后,此时路由跳转已经完成,
主要用于进行一些不需要等待导航完成的操作,如分析、记录等。
afterEach是全局后置守卫,它在路由跳转完成后被调用
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
// 定义你的路由...
]
const router = createRouter({
history: createWebHistory(),
routes,
})
// 使用 afterEach 守卫
router.afterEach((to, from) => {
* 这里的逻辑,会在每次路由跳转完成后执行
* 例如,我们可以记录一些导航信息
console.log('Navigation Completed:', to.path)
* 发送统计信息到服务器
sendAjax({ fromPath: from.path, toPath: to.path })
* 清除页面级别的临时数据
// clearPageLevelData()
* 其他需要在路由跳转后执行的操作....
})
11、触发 DOM 更新
Vue 开始更新 DOM 以反映新的路由
12、调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入
如果,在 beforeRouteEnter 守卫中传递了一个回调函数给 next,
那么,在这个阶段会调用这个回调函数,
此时,组件实例
已经被创建,并会作为回调函数的参数
传入。