likes
comments
collection
share

🤡官:你有遇到很难排查的问题吗

作者站长头像
站长
· 阅读数 26

前言


当别人给你发红包,如果你不想收~ 你这样回:心意和红包,我就挑最贵重的收下啦,红包就不收了,谢谢!

🤡官:你有遇到很难排查的问题吗

地铁上看到一个文质彬彬的少年~

一、场景还原

请允许我用最简单朴素的话描述。

从A路由—>B路由,此时停留在B路由页面下,点击浏览器自带的返回,期望回到A页面。

🤡官:你有遇到很难排查的问题吗

结果发现:url是A页面的,但内容还是B页面。

而当前应用是嵌入到其他环境的,被包裹了一层。

二、分析

首先,有请第一位怀疑对象登场。

2.1 beforeEach

初步怀疑是router.beforeEach的哪个逻辑没有走next(),所以导致他停留下来。

我们写程序的时候,应该要有这种直觉。

于是,我们查看逻辑,发现此时调用H接口成功时,才会去走next()。

那是否是因为网络导致接口响应慢,而影响了next。

2.2 浏览器历史记录

正当我们调试一波,部署线上时,神奇的发现,点击【返回】的时候,连router.beforeEach都不走,这就有点神奇了。

心想:路由的一切变化,应该都会走beforeEach才对的,尽管的浏览器或者路由跳转。

于是,我咨询了一位朋友。

在使用 Vue Router 中,当使用 history 模式(HTML5 History 模式)时,浏览器返回上一个页面会触发浏览器的历史记录操作,而不会触发 Vue Router 的路由跳转。因为 Vue Router 的 beforeEach 守卫是在路由跳转之前触发的,而浏览器的返回按钮并不是触发路由跳转,而是操作浏览器历史记录。

所以,当用户点击浏览器返回按钮时,页面会直接从浏览器历史记录中获取上一个页面的 URL,并加载对应的页面内容,这个过程是浏览器自身的行为,不会经过 Vue Router,因此也不会触发 beforeEach 守卫以及其他 Vue Router 相关的路由导航守卫。

如果您希望在用户点击浏览器返回按钮时执行一些逻辑,可以使用浏览器原生的 popstate 事件来监听浏览器的历史记录变化。在 popstate 事件中,您可以执行相关的逻辑操作。但是需要注意的是,这种方式不会触发 Vue Router 的路由导航守卫。

完。

我看完是想笑的,虽然心里有一度觉得有点道理,但不管是浏览器操作历史记录,还是会走beforeEach守卫的,她是全局的。

🤡官:你有遇到很难排查的问题吗

2.3 popstate

提到了一个点,说可以利用popstate事件来执行路由跳转,可以router.go(-1) ,但我认为不好,因为无法确认他会不会走beforeEach,要是走了,里面next,你popstate也go(-1),就会跳转两次。

Out!

2.4 组件路由守卫

没事,我还有招,竟然全局的路由守卫,我还有其他守卫,我去组件守卫添加一下beforeRouteLeave让她next。

很遗憾,这里也不会执行。

Out!

2.5 外部js影响?

在html中,我们引入了n个js资源,如:wx的,埋点SDK等等。

是否是因为这些js资源引起,某个代码阻止了其跳转事件。

也有这个可能,但排查起来困难,因为引入资源较多。

2.6 找规律:刷新

如果阁下,阁下会怎么排查?

我将项目的对象都怀疑了一遍,突然想起小时候老师说的,遇到问题不要慌,先找问题所在,那怎么找问题呢?

找规律!

🤡官:你有遇到很难排查的问题吗

我们的应用,是嵌入到其他应用的,那边点击一个按钮a标签会跳转到我们这边来,其实一开始怀疑是不是那边有什么限制,比如nginx设置了。

但发现,在同等的其他应用没有这个情况,那还是我们自己先找原因。

回归正题,跳到我们应用来,A路由—>B路由。

突然发现:如果我们此时在任意的路由手动F5刷新一下,即可正常回退上一步。

有了这个规律,我突然想起,之前有一个需求:

url?token=base64,由于token很长,而且会显示在页面上,希望我们拿到token存到vuex中,用js程序把url上的token给清除掉。

delete to.query.token;
router.push({ name: to.name, query: {...to.query  }  });

即:

url?token=1

url

我想,或许和这里有关,导致路由、历史记录错乱,才会回退不回去。

然后我们手动刷新一下,记录就正常了,也就能正常回退。

三、解决方法

有两个解决方法。

3.1 去掉自动删除token

这一步去掉。

delete to.query.token;
router.push({ name: to.name, query: {...to.query  }  });

直接走next。

当然,原本的需求,我们最好不要去做更改,只能程序自己想办法了。

3.2 自动刷新

既然刷新能解决问题,那我们就让他进入我们的应用的时候,刷新一下,在源头处理就好。

源头解决好了,后面的路由跳转就没问题了。

我们只页面加载第一次的时候,做手动刷新。

mounted(){
  if(this.$store.getters.get_isFirstRefresh){
    this.$store.dispatch('set_isFirstRefresh',false);
    this.$router.go(0) // 刷新
  }
}

vuex

const homeInfos = {
    state: {
        isFirstRefresh: true 
    },
    mutations: {
        set_isFirstRefresh(state, isFirstRefresh) {
            state.isFirstRefresh = isFirstRefresh
        }
    },
    actions: {
        set_isFirstRefresh(state,isFirstRefresh) {
            state.commit('set_isFirstRefresh', isFirstRefresh)
        }
    },
    getters: {
        get_isFirstRefresh: (state) => {
            return state.isFirstRefresh
        }
    }
}

export default homeInfos

至此撒花~

后记

我们在实际项目中或多或少遇到一些奇奇怪怪的问题。

在此期间,不要慌是首选,多凭借自己的经验找感觉,或许是有一个需求改了一两行不起眼的代码导致。

大动脉没切中,即安心。

如果有其他更好的方法也欢迎评论区见,这里提供的只是诸多方法之一。

最后,祝君能拿下满意的offer。

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

原文链接

转载自:https://juejin.cn/post/7385966245587533876
评论
请登录