前端渣渣記一次排查萬惡之源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)

相關文章
相關標籤/搜索