那些與 IE 相伴的日子

這是第 91 篇不摻水的原創,想獲取更多原創好文,請搜索公衆號關注咱們吧~ 本文首發於政採雲前端博客: 那些與 IE 相伴的日子

前言

Internet Explorer(簡稱:IE)是微軟公司 爲了對抗 網景瀏覽器(NetscapeNavigator)從而投入開發,並於 1995 年推出的一款網頁瀏覽器,曾經一度成爲同 Windows 系統捆綁安裝的流氓軟件橫行於世,也佔據了極高的市場份額,但在近些年裏,它卻一直由於自己的落後而被衆多用戶和開發者詬病。css

現在,即使是連微軟公司本身都放棄了更新 IE,但一衆 Web 開發者們爲了部分仍在堅持使用 IE 瀏覽器的用戶,卻依然不得不向下兼容,筆者也是其中的一員,本篇文章記錄了我在工做期間爲了兼容 IE ( IE9及以上 )作過的一些調整。html

模擬 IE 版本環境

許多開發者們的電腦自己是 Mac 系統,是沒法安裝 IE 瀏覽器的,這個時候就須要安裝虛擬機提供 Windows 環境測試 IE 瀏覽器下的效果了。然而安裝的虛擬機比較佔用空間,這個時候,借用另外一臺 Windows 系統的電腦,訪問 Webpack (或其餘編譯打包器)配置的局域網下的頁面地址,以此調試,也不失爲一個好選擇。前端

許多國產瀏覽器也提供了極速、兼容的雙內核模式,極速模式下使用 Chrome 等非 IE 內核、兼容模式下使用 IE 內核,以應對不一樣頁面的使用,打開控制檯,能夠切換模擬不一樣的 IE 版本(儘管只是模擬,有些時候並不許確)。node

兼容 IE 下的樣式

其實不少瀏覽器不兼容的問題咱們均可以從這個網站 caniuse 上查詢到,不止 IE,還包括 Safari、Firefox 以及他們在安卓系統中對應的瀏覽器兼容能力也被很好的總結在這裏了。然而,咱們是很難一次性查完全部的差別點再投入開發的,這裏分享幾個我在開發中遇到的問題,以及對應的解決方法吧。webpack

1)圖片定寬不定高會變形

在我日常作首屏 Banner 大圖的時候,有時候爲了快,直接寫一個寬度 width: 1200px 就以爲萬事大吉了,在 Chorme 上確實也表現良好,不負所望,可是當測試到 IE九、IE10 時,都會存在一個問題是圖片變形,以下圖所示。git

當我打開 IE 瀏覽器的 DOM 資源管理器的時候發現,IE 瀏覽器對我<img /> 標籤多添加了一段這樣的屬性: width="824" height="300",而這個寬度和高度是從哪裏來的呢?我選中下載下來的圖片,右擊查看詳情,發現這個圖片文件自己的寬度和高度就是 824px 和 300px,因而答案即可以知曉了。es6

當我設置圖片標籤的 src 的時候, IE 瀏覽器自動將原圖片的寬、高設置成了 <img /> 的屬性,這樣致使我使用 CSS 只設置寬度爲 1200px 而沒有設置高的時候,<img /> 的生效高度即是原圖的高度 300px。而 Chrome 對<img /> 標籤什麼都沒有添加,因此標籤的高度 height 也就是按照圖片等比例縮放後的高度,不會變形。github

  • Chrome 下的表現

  • IE 下的表現

解決方法也很簡單,就是在 <img /> 標籤的的 class 樣式裏,再添加一個簡單的 height: auto; ,同時對寬高進行設置,覆蓋掉原標籤自動添加的寬度和高度,這樣就能夠解決變形的問題了。web

2)IE 下 8 位色值不生效

在以前的開發中,我都習慣了使用 6 位色值,也未曾出現過問題,直到有一次,運營同窗反饋在組件配置平臺下選中了某個顏色,卻一直不生效,經過排查問題,才發現了原來輸出的色值是 8 位,而正是這多餘的兩位,在 IE 瀏覽器下並不通用。npm

咱們知道,CSS 顏色使用組合了紅、綠、藍顏色值 (RGB) 的十六進制 (hex) 表示法進行定義,十六進制值使用三個雙位數來編寫,並以 # 符號開頭(如:\#FF0000),同時, Chrome 瀏覽器支持 8 位色值(如 #FF0000ee),最後兩位表示不透明度 Alpha 值,其中 00 表示不透明度爲 0,也就是全透明狀態,FF 表示不透明度 100%,也就是全不透明狀態,但在 IE 瀏覽器下不支持。

IE 狀況下,使用 8 位色值,不但最後兩位的不透明度沒法生效,反而整個顏色設置都不能生效,下面是一個簡單的 Demo 來模擬這種狀況,標題的顏色設置不生效,因此呈現出默認的黑色狀態。

解決方法也比較簡單,在這種場景下,不透明度不是必須的,能夠刪除掉最後兩位,僅使用 6 位色值便可。若是實在須要不透明度,咱們可使用 rgba 的格式,用最後一位值來實現透明度,如background-color: rgba(255,0,0,0.3),即便在 IE9 上也能夠表現良好。

3)處理左右鏡像

IE9 支持了 CSS3 的許多屬性,但仍是有許多力所不能及的地方。好比,有一次的開發場景是但願在標題的兩邊作出對稱的兩種圖樣,因而我對這張圖拷貝出來的第二份設置了 transform:rotateY(180deg); 讓圖片繞 Y 軸旋轉,IE9 雖然已經支持了 trasform 2D 旋轉,可是並不支持 trasform 3D 旋轉,因此會出現以下所示的問題。

這裏咱們可使用 IE9 支持的canvas畫布將座標軸翻轉 ,繪製圖像,就能獲得一個左右對稱的圖片了。Html 中須要對原始 <img /> 標籤進行寬度和高度的顯式設置,才能保證 <canvas> 中有準確的寬高。代碼以下。

getRotateImg = (imgSourceId = '') => {
    const imgNode = document.getElementById(imgSourceId);
    const canvas = document.createElement('canvas'); 
    canvas.setAttribute('id', 'canvas');
    // 設置 canvas 的寬高,防止變形 
    canvas.setAttribute('width', imgNode.style.width); 
    canvas.setAttribute('height', imgNode.style.height); 

    const width = parseInt(imgNode.style.width);
    const height = parseInt(imgNode.style.height);
    
    var ctx = canvas.getContext('2d');
    var img = new Image();
    img.src = imgNode.src;
    
    imgNode.parentNode.appendChild(canvas); 
    img.onload = function() {
      console.log(imgNode.style.width);
      // 將座標原點移動到畫布最右端,使反向圖片向左繪製,呈如今畫布範圍內
      ctx.translate(width, 0);
      //左右鏡像翻轉座標系
      ctx.scale(-1, 1); 
      ctx.drawImage(img, 0, 0, width, height);
    }
 }

實際效果如圖所示。

4)放棄 Flex 佈局

在初識 Flex佈局 (彈性佈局)的時候,會喜歡上它的靈活簡單,可是 IE9 下並不支持 Flex 佈局,咱們能夠用其餘方式來代替。

好比咱們能夠這樣經過display: tabledisplay: table-cell實現一個簡單的等分效果,在這種狀況下,傳統的 margin 沒法提供外邊距,咱們可使用 border-space 代替。

<div class="wrapper-2">
  <div class="flex-2">4 等分</div>
  <div class="flex-2">4 等分</div>
  <div class="flex-2">4 等分</div>
  <div class="flex-2">4 等分</div>
</div>

CSS 代碼

.wrapper-2 {
  height: 100px;
  width: 80%;
  margin: 20px auto;
  background-color: wheat;

  display: table;  /* 主要代碼 */
  border-spacing: 30px;  /* 主要代碼 */
}
.flex-2 {
  background-color: pink;
  padding: 10px;
  text-align: center;
  border: solid 2px purple;
  
  display: table-cell; /* 主要代碼 */
}

或者使用text-align: center,vertical-align: middle 配合 display: inline-block 達到相似的效果,以下:

.wrapper-3 {
    height: 200px;
    width: 80%;
    margin: 20px auto;
    background-color: wheat;
    line-height: 200px;

    text-align: center; /* 主要代碼 */
  }
  .flex-3 {
    width: 80px;
    line-height: 100px;
    background-color: pink;
    margin: auto 20px;
    height: 100px;
    border: solid 2px purple;
    text-align: center;

    display: inline-block;   /* 主要代碼 */
    vertical-align: middle;  /* 主要代碼 */
    
  }

關於 CSS Hack

CSS Hack 的原理是根據不一樣瀏覽器和瀏覽器不一樣的版本對 CSS 的解析不一樣,分別書寫不一樣的代碼加以應對。常見的寫法有 3 種:條件註釋法、CSS 屬性前綴法、選擇器前綴法,通常寫 Hack 的順序是:從最新版本到低版本,好比:新版本、IE(10/9/8)、IE(7/6),具體寫法能夠參考這篇文章《CSS Hack 合集》

可是過多地依賴 CSS hack 會致使代碼很是的不整潔,也可能會對後續的兼容留下隱患,因此實際不多使用。

例如這些:

只在IE下生效
<!--[if IE]>
這段文字只在IE瀏覽器顯示
<![endif]-->

只在IE6下生效
<!--[if IE 6]>
這段文字只在IE6瀏覽器顯示
<![endif]-->

IE9 不支持 History 路由

在單頁面應用中,存在着前端路由的概念,哈希路由兼容性好,可是 URL 老是存在着/# 會讓人以爲有些很差看,因而咱們想到了清爽簡潔的 History 路由。

然而,在 IE 9 條件下,因爲缺乏 window.history 對象,天然也不能調用 history.pushStatehistory.replaceState 方法,因此 Chrome 下可以正常使用的 History 路由模式不能生效。這個時候咱們有幾種解決方案了,一是選擇哈希路由,二是直接作成多頁面應用,跳轉時刷新整個頁面,也能夠選擇使用 history.js ,裏面已經實現了常見的 History 路由的 Api。

在 IE 上使用 ES6

@babel/polyfill

IE 不支持許多 ES6 的語法,好比 Array.from(),Object.assign() 等常見函數,因此咱們可使用工具鏈 Babel 中的 @babel/polyfill 將代碼轉換成能夠向後兼容、在低版本上也可以使用的的語法,好比這樣:

// 咱們書寫的原始代碼
[1, 2, 3].map((n) => n + 1);

// 通過轉換後的代碼
[1, 2, 3].map(function(n) {
  return n + 1;
});
npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
  • 在 node 環境中使用

    require("babel-polyfill");

  • 在 es6 中使用

    import "babel-polyfill";

  • 在 webpack 中使用

    module.exports = {
     entry: ["babel-polyfill", "./app/js"] 
    };

以在 webpack 中配置爲例,webpack.config.js 代碼以下:

var path = require("path");

module.exports = {
  entry: {
    entry: ["@babel/polyfill", "./index.js"], // 在入口文件 index.js 前面加入 "@babel/polyfill" 這個配置
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader", // 須要安裝 babel-loader 此配置可將全部 js,jsx 後綴的文件進行轉換
          options: {
            babelrc: false,
            presets: [
              [require.resolve("@babel/preset-env"), { modules: false }], // webpack 已作了模塊化打包,因此此處 modules 裏
            ],
            cacheDirectory: true,
          },
        },
      },
    ],
  },
  plugins: [],
};

總結

以上是我在兼容 IE(IE9 及以上) 過程當中踩過的坑和進行的調整了。技術是死的,應用倒是活的,咱們應當掌握常見的兼容能力,但有時候,絞盡腦汁地向下兼容反而不如換一個更靈活、成本更低的方式表達。咱們期待着多年之後,用戶們可以放棄 IE ,擁抱更敏捷好用的瀏覽器,迎接一個新的時代。

參考文檔

JS 實現兼容IE圖片向左或向右翻轉

CSS Hack 合集

招賢納士

政採雲前端團隊(ZooTeam),一個年輕富有激情和創造力的前端團隊,隸屬於政採雲產品研發部,Base 在風景如畫的杭州。團隊現有 40 餘個前端小夥伴,平均年齡 27 歲,近 3 成是全棧工程師,妥妥的青年風暴團。成員構成既有來自於阿里、網易的「老」兵,也有浙大、中科大、杭電等校的應屆新人。團隊在平常的業務對接以外,還在物料體系、工程平臺、搭建平臺、性能體驗、雲端應用、數據分析及可視化等方向進行技術探索和實戰,推進並落地了一系列的內部技術產品,持續探索前端技術體系的新邊界。

若是你想改變一直被事折騰,但願開始能折騰事;若是你想改變一直被告誡須要多些想法,卻無從破局;若是你想改變你有能力去作成那個結果,卻不須要你;若是你想改變你想作成的事須要一個團隊去支撐,但沒你帶人的位置;若是你想改變既定的節奏,將會是「5 年工做時間 3 年工做經驗」;若是你想改變原本悟性不錯,但老是有那一層窗戶紙的模糊… 若是你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的本身。若是你但願參與到隨着業務騰飛的過程,親手推進一個有着深刻的業務理解、完善的技術體系、技術創造價值、影響力外溢的前端團隊的成長曆程,我以爲咱們該聊聊。任什麼時候間,等着你寫點什麼,發給 ZooTeam@cai-inc.com

相關文章
相關標籤/搜索