根据官网文档的介绍,组件的守卫是有beforeRouteEnter,beforeRouteUpdate和beforeRouteLeave。beforeRouteUpdate和beforeRouteLeave可以访问组件实例,所以setup函数中可以使用,而beforeRouteEnter 守卫不能访问,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建,setup函数是在组件创建之前就执行了。如果使用的语法是setup,那么助setup函数中自定义方法onBeforeRouteEnter与组件beforeRouteEnter关联实现。
方法一在路由配置文件中使用:
const routes=[ { path:"/", component:Home.vue, beforeEnter(to,from)=> { // 做点什么 } }]
方法二在组件文件中(本文重点):
<script> import { defineComponent } from "vue"; export default defineComponent({ beforeRouteEnter (to, from, next) { //暴露一个去调用 <script setup> 暴露的方法 next((instance) => { // 组件实例化完成后执行next里面的回调函数,instance是组件实例。Vue 会调用这个回调,并将组件实例作为参数传递给它 const routeFrom = from //将要传递出去的数据 instance.onBeforeRouteEnter(routeFrom) }); }, }); </script> <script setup> const onBeforeRouteEnter = async (routeFrom) => { if (routeFrom.path === "/") { // to do someting } } defineExpose({ onBeforeRouteEnter, }); </script>
这里解释一下上半部分代码:
首先通过defineComponent定义了当前的组件,并且在组件守卫中执行了next方法。next方法中回调的参数就是当前组件的实例。当组件守卫beforeRouteEnter执行,并且执行了next方法,这个时候组件实例化完成,组件实例再执行一个组件自定义的方法onBeforeRouteEnter。这个自定义方法携带一个参数:来源路由对象。那么这个自定义方法来自哪里?怎么定义的?
下半部是在setup函数中定义了一个组件的自定义方法。这个setup函数中的方法就是前面组件实例调用的方法,这样两部部分关联了起来。
这里需要注意这个自定义的方法,是需要通过defineExpose暴露出去,这样父组件(defineComponent定义的组件)实例化之后也就是instance,就可以调用这个方法。
这样巧妙的就可以在<script setup> 语法或者setup()函数中调用onBeforeRouteEnter,,相当于调用beforeRouteEnter。