前端渣渣记一次排查万恶之源IE兼容性的问题

🙃 兼容性 BUG 万恶之源 : IE 浏览器html

昨天晚上,原本舒舒服服的躺在被窝睡觉,睡前一看企业邮箱,哦豁,好家伙,给我报了四个BUG,我再进入一看,映入眼前的是 : 360兼容模式下,在A页面点击按钮没法跳转IE浏览器在B页面点击返回按钮无效果,停留在当前页面C页面弹窗按钮,点击以后,弹窗没关闭,点击无效果...node

什么鬼,玩我呢?这几个 BUG 的最终缘由都是IE上没法跳转(小声逼逼,测试说操做步骤不一样,我心累了)因而今天早上,再次踏上漫长的 fix bug 之路。react

代码

咋,还能代码有问题?相信这段代码,你们都会写吧?浏览器

<Button onClick={this.backEvent} />
复制代码
backEvent = () => {
  // 返回前作些其它的处理
  let cb_function = dosomething();

  const { history } = this.props;
  if (history) {
    history.push(cb_function);
  }
};
复制代码

而后跑项目,找到页面所在的位置,点击返回,果真,gg了react-router

这啥鸡儿玩意,什么叫作对象不支持此操做,咋滴,变脸了呢,在 Chrome 下你可不是这样的。函数

排查

既然它说这个对象不支持这个操做,那是指 history 对象不支持这个PUSH操做?测试

因而我去把这个玩意,打印了一下ui

玩尼玛呢,有的啊,这什么骚操做,为啥就报错了???this

因而我又去项目中,看了一下关于 this.props.history.push 的正确使用方式,就是这么写的啊。wc !spa

<!-- 项目中其它地方用到的 this.props.history.push -->
<!-- 代码真实跳转路径和文案已被我和谐 -->
<div styleName="item" onClick={() => {
    this.props.history.push('/juejin');
  }}
>
  跳到掘金
</div>
复制代码

难道是我写这段代码以前没有烧香拜佛的缘由?没办法了,只可以,使用必杀技了,debugger !!!

Debugger

先来 debugger 能够正常跳转的代码。

这个 push 方法是 react-router 注入的,咱们能够 debugger 看到,进入了 pushState 中,紧接着咱们继续 debugger

再往下,发现进入了 setState({ action, location }), 接着推入栈

结果就是 : 成功跳转!!!

咱们再来 debugger 一下异类的代码,在 IE 中,一步一步 debugger。在这里建立了一个 location 对象

紧着着,这里会使用 createHref(location) 函数,生成一个 href 对象,获取 keystate

目的就是在可使用 react-router注入的 history 中,去操做 pushState 方法。

没毛病,可是,到了这里以后,再往下走,就跳到了一个名为 : useLocation.js 的文件中

在这个文件夹中,就报了 对象不支持此操做。就很骚气。 what ????? 这什么鸡儿玩意啊,卧槽

猜想

首先怀疑是 pushState 的兼容性问题,因而去看了一下兼容性

果真本身仍是太蠢了,回过头想一想,要真是 pushState 兼容性问题的话,那么第一个跳转也不可能成功。

难道是个人问题?仍是 react-router 的问题?仍是 IE 问题?

解决

其实并无解决,由于我真不知道如何解决了,因此用了降级方法,就是 window.location.href 原生方法。

react-router 对于不可以使用 canUseHistory 时,也是采用的 window.location.href

// 部分代码无偿奉献
function push(path, state) {
  var action = 'PUSH';
  // 获得一个 location 对象
  var location = createLocation(path, state, createKey(), history.location);

  transitionManager.confirmTransitionTo(
    location,
    action,
    getUserConfirmation,
    function(ok) {
      if (!ok) return;
      // 建立一个 href 对象
      var href = createHref(location);
      var key = location.key,
        state = location.state;

      if (canUseHistory) {
        // 第二个不可跳转的,就死在了这里,我也不知道为何
        globalHistory.pushState({
            key: key,
            state: state
        }, null, href);

        if (forceRefresh) {
          window.location.href = href;
        } else {
          // 第一个能够跳转的就进入到了这里
          var prevIndex = allKeys.indexOf(history.location.key);
          var nextKeys = allKeys.slice(0, prevIndex + 1);
          nextKeys.push(location.key);
          allKeys = nextKeys;
          setState({
            action: action,
            location: location
          });
        }
      } else {
        // 原生跳转
        window.location.href = href;
      }
    }
  );
}
复制代码

再次出现问题

在我使用 window.location.href 解决了上述的问题以后,我觉得此事到此结束,可是!!!又出问题了,什么问题呢?测试报了一个现象 :

首先进入项目主页面,此时的 breadcrumb 面包屑均可以跳转(使用的history.push),以后进入到 A 页面,在 A 页面中点击 返回 按钮(此时的返回经过 window.location.href)实现了。成功返回以后,再次点击 breadcrumb ,无响应,不跳转了。

我懵逼了,这是什么鬼玩意啊,总不能将整个项目的跳转方式都换成 window.location.href 吧,因而,再次去排查

Event

咱们看到,它报了一个 Event 错误

const event = new Event()
复制代码

OK,你牛逼 👍,除了牛逼没啥说的,那咋办,在汉鑫哥的帮助下,一块儿排查,定位到了 useLocation 文件上,前边好好的可跳转,都没这个文件的啥事,咋这里就有这个玩意了呢?这个文件是哪来的?

再一看,原来这个文件是在 react-use 里边的,恰好在 A组件中,使用到了这个库,去 node_modules 中找这个文件,看到这段代码

没毛病啊,这是啥状况,再次进行 Debugger,发现,只要没引入这个 A组件,那么在 IE 上,均可以正常跳转,在引入了这个 A组件(也就是用了这个库),就出问题了。

为了验证这个问题,把项目中用到 react-use 的都注释掉(幸亏就一个组件用到了这个库),重启,打开IE,怀着激动的心情,去试了一下,卧槽!!!!竟然能够了!!!!!

问题应该是,本来应该pushState的,在引入这个组件(加载这个库)了以后,就都被hack掉了,以后的跳转,都经过 Event,而 Event 在IE上又不兼容,因此凉了。(我的猜想)

最后

千呼万唤始出来,我尿了,IE真的是太难过,每次作个东西,都要兼容IE、Edge,我心里是崩溃的,不过感谢IE,让我更加有耐心了,比哄女友还更加有耐心,感恩有你 (微笑.jpg)

相关文章
相关标签/搜索