vue-router 完整的导航流程解析

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,

那么,在这个阶段会调用这个回调函数,

此时,组件实例已经被创建,并会作为回调函数的参数传入。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值