【vue-router②】使用导航守卫控制页面前进刷新,后退缓存
之前给大家分享了利用keep-alive进行缓存你想要的页面,然后到后面会出现这样的问题:
我有三个组件A(组件)、B(A中的弹框)、C(组件),其实算是两个组件,一个弹框,现在他们的关系是这样的:
点击A(li循环列表组件)中某个功能,弹出了B(弹框-表格),然后在B(弹框)点击连接跳转到C(组件)。
然后我想要实现A(li循环列表组件)缓存,B(弹框-表格)根据A的传参实时刷新,C(组件)根据B的传参实时刷新,A->B->C。
接下来返回依次从C->B->A,如下图:
1、B是一个弹框,和A处于同一个组件,从C返回要看到B的话,就要实现A缓存,即C返回A的时候A没刷新还保持弹框不变就可以实现C是退回B,这个用前面说的keep-alive就可以实现。
2、这时候从B->A(我们这边退回按钮设置关闭弹框是可以实现B->A的),点击的是浏览器或者手机的回退键,就会发现,并没有实现这一步,而是B直接退到A的前一页,因为系统的回退键记录的是历史路由,而B和A本身就是一个路由,所以就会出现这种情况。
这时候的解决办法就是:判断路由离开前,B弹框是否打开,若是打开就先关闭弹框,不允许路由跳转,所以就可以造成B回退到A的假象。这时候利用的是beforeRouteLeave钩子。实现如下:
beforeRouteLeave(to,from,next) { //B是B弹框的v-model值 if (this.B) { this.B= false; next(false); } else { next(); } }
3、然后接下来你就会发现另一个问题,就是B->C的时候,因为B是打开的,上面的判断就会造成B无法跳转到C,但是没设置上面的代码,就会造成C回退的时候,要么是到C->A(A不设缓存,实时刷新)->A前面的页面,要么C->B(A设缓存,不刷新就保持B)->A前面的页面,无论是那种情况都不是我们想要的。
解决:还是使用beforeRouteLeave,再加一层判断,当路由跳转的目标是C的时候,next设为true,若是其他跳转则设为false。
(1)判断目标路由是C的时候,保持B为true,这样C->B,
(2)当B后退的时候,判断B打开,则先关闭B,不后退,这样就能B->A
(3)A再回退的时候,B已经为false,所A就可以再返回到它的上一级。
beforeRouteLeave(to,from,next) { /*to:目标路由 * from:当前要离开的路由 * */ if(to.name === "C"){ if(this.B){ this.B= true; next(); } else{ next();} }else { if (this.B) { this.B= false; next(false); } else { next(); } } },
这里就可以实现我要的回退顺序及效果。
说到beforeRouteLeave,就不得不跟大家提一下v-router的导航守卫,可参考官方文档。
现在我来说下我对于组件内的守卫的一个理解。共有三个:
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` } }
三者都能接收三种参数:to, from, next
顾名思义,
beforeRouteEnter :表示在进入当前组件前的一个操作,它执行顺序是很靠前的,而其中next的回调勾子的函数,执行则非常靠后,在mounted之后!!
我们通常是在beforeRouteEnter中加载一些首屏用数据,待数据收到后,再调用next勾子,通过回调的参数vm将数据绑定到实例上。
因此,请注意next的勾子是非常靠后的。
beforeRouteEnter(to, from, next) { next(vm => { if(to.name == '目标路由名称'){ //vm.fetchData() }else{ //vm.fetchData() } }) }
beforeRouteUpdate :表示在当前组件改变之前,这个还没用过,具体我也不太清楚里面的情况,后面用到再做介绍。
beforeRouteLeave :表示在当前组件离开之前,这个就是我的最爱了,现在对于组件的状态控制,我可都是依赖它的,像上面提到的控制弹框和跳转。