Vue 兼容 ie9 的周全解決方案

媒介

背景狀況

  • vue – 2.5.11
  • vue-cli 運用模板 webpack-simple
  • http要求:axios

Vue 官方關於 ie 閱讀器版本兼容狀況的形貌是 ie9+,等於 ie9 及更高的版本。經由測試,Vue 的中心框架 vuejs 自身,以及生態的官方中心插件(VueRouter、Vuex等)均能夠在 ie9 上一般運用。

Vue 的作者尤雨溪關於 Vue 的進修提議 中有說起為了將項目更好的生態化/工程化,要盡量進修及運用新的 ECMAScript 範例。現在 ES6/ES2015 是可費用和穩固度較高的範例,文檔完整,國內另有 阮一峰 《ECMAScript 6 入門》 做了大批的文檔翻譯,開闢環境可謂圓滿。但是版本較舊的閱讀器並不支持 es6 範例,尤其是 ie 閱讀器,縱然是最高的 ie11 版本,關於 es6 範例也支持得並不全。云云則須要對一切原生不支持 ES6 特徵的閱讀器做兼容性處置懲罰。

本文將針對運用 Vue 生態開闢完成的網站,以 ie9 版本為基本兼容目標,完成全功用一般運用的周全兼容處理計劃。

ES6兼容

在 ie9 的環境上,es6 的部份新對象、表達式,並不支持,處理計劃是運用 babel-polyfill 組件,它能夠將 es6 的代碼翻譯成低版本閱讀器能夠辨認的 es5 代碼

npm i babel-polyfill --save-dev

裝置完成后,在項目標主進口文件 main.js 的首行就能夠直接援用

import 'babel-polyfill';

在項目運用 vue-cli 天生的代碼中,根目錄有一個 .babelrc 文件,這是項目運用 babel 的設置文件。在默許天生的模板內容中,增添 "useBuiltIns": "entry" 的設置內容,這是一個指定哪些內容須要被 polyfill(兼容) 的設置

useBuiltIns 有三個設置選項

  • false – 不做任何操縱
  • entry – 依據閱讀器版本的支持,將 polyfill 需求拆分引入,僅引入有閱讀器不支持的polyfill
  • usage – 檢測代碼中 ES6/7/8 等的運用狀況,僅僅加載代碼中用到的 polyfill

這裏引薦設置為 entry ,完整的 .babelrc 內容以下:

{
  "presets": [
    [
      "env",
      {
        "modules": false,
        "useBuiltIns": "entry"
      }
    ],
    "stage-3"
  ]
}

到場這些代碼后,工程里的大部份內容已可兼容到 ie9 版本

Number對象

縱然在運用 babel-polyfill 做代碼翻譯后,發明照樣有一些 es6 的新特徵並沒有處理,比如說 Number 對象的 parseIntparseFloat 要領

es6 將全局要領 parseInt()parseFloat() ,移植到 Number 對象上面,行動完整堅持穩定。如許做的目標,是逐漸削減全局性要領,使得言語逐漸模塊化。

處理這個題目不須要引入包來處理,同樣在項目主進口文件 main.js 到場以下代碼(代碼盡量靠前,最好是在援用 babel-polyfill 以後 )

if (Number.parseInt === undefined) Number.parseInt = window.parseInt;
if (Number.parseFloat === undefined) Number.parseFloat = window.parseFloat;

requestAnimationFrame要領

window.requestAnimationFrame 是閱讀器用於定時輪迴操縱的一個接口,類似於 setTimeout,主要用途是按幀對網頁舉行重繪。

requestAnimationFrame 的上風,在於充分應用显示器的革新機制,比較節約體系資源。显示器有牢固的革新頻次(60Hz或75Hz),也就是說,每秒最多只能重繪60次或75次,requestAnimationFrame 的基本思想就是與這個革新頻次堅持同步,應用這個革新頻次舉行頁面重繪。另外,運用這個API,一旦頁面不處於閱讀器的當前標籤,就會自動住手革新。這就節約了CPU、GPU和電力。

不過有一點須要注重,requestAnimationFrame 是在主線程上完成。這意味着,假如主線程異常忙碌,requestAnimationFrame 的動畫結果會大打折扣。

window.requestAnimationFrame() 要領通知閱讀器您願望實行動畫並要求閱讀器鄙人一次重繪之前挪用指定的函數來更新動畫。該要領運用一個回調函數作為參數,這個回調函數會在閱讀重視繪之前挪用。

有部份第三方組件就運用了這個要領,比方部份文件上傳、圖片處置懲罰類的組件;那末在這範例的組件在 ie9 下運用時,會報出

SCRIPT5007: Expected object.

window.requestAnimationFrame() 的最低兼容 ie 版本為 10,那末在 ie9 上做兼容就須要製造 requestAnimationFrame polyfill

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

Gist:requestAnimationFrame polyfill

這部份代碼同樣是盡量在網站進口處就實行

http收集要求(跨域)

在大多數的 Web 項目中(以 JavaWeb 為例),網站的頁面和效勞(至少是 controller 層)在一致個工程舉行開闢和布置,在大前端的新型形式下,我們提議盡量對網站的前端和後端舉行完整星散,前後端星散的長處和意義這裏不再贅述。

既然是前後端星散,那末布置也必定是各自自力布置,差別的接見途徑,就會發生跨域接見的題目(一致站點,差別端口號也是跨域)

在此設定背景狀況:

  • 效勞端已完整開啟 CROS 跨域支持
  • http 組件運用 axios
  • axios 設置 withCredentials 為 true 開啟跨域接見時照顧 cookie 數據

高版本閱讀器(ie10+ 或 chrome, ff)僅須要完成背景狀況中的功用,即可支持跨域數據要求功用

axios 舉行數據要求時,默許運用 XMLHttpRequest 對象,在檢測到當前要求是跨域接見時,axios 會測試閱讀器是不是支持 XDomainRequest 對象,若支持則優先運用。

ie8 / ie9 的 XMLHttpRequest 對象,不支持跨域接見,該對象在 ie10 后才原生支持跨域接見。微軟的處理計劃是在 ie8 / ie9 中供應了 XDomainRequest(XDR) 對象來舉行處理跨域題目,雖然運用該對象能夠跨域接見勝利,並返回數據,但它卻依然是一個功用不完整的半成品,它的運用有諸多限定:

  • XDR 僅支持 GET 與 POST 兩種要求體式格局
  • XDR 不支持自定義的要求頭,若效勞端運用 header 的自定義參數舉行做身份驗證,則不可用
  • 要求頭的 Content-Type 只允許設置為 text/plain
  • XDR 不允許跨協定的要求,假如網頁在 HTTP 協定下,就只能要求 HTTP 協定下的接口,不能接見 HTTPS 接口
  • XDR 只接收HTTP/HTTPS 的要求
  • 提議要求的時刻,不會照顧 authenticationcookies

微軟雖然供應了處理計劃,但倒是不折不扣的雞肋,基礎沒法勝任體系中種種場景的數據要求需求,至此,axios 對 ie9 的跨域數據要求已無計可施。

圓滿處理計劃:代辦(proxy)

雖然 axios 對 ie9 跨域已無計可施,但前端項目打包的處理計劃 webpack 供應了一個文雅而完全處理題目的體式格局:代辦

devServer.proxy

webpack 的 devServer.proxy 的功用是由 http-proxy-middleware 項目來完成的

完成道理是將目標位置的要求代辦為前端效勞當地的要求,既然是代辦成為當地的要求,就不存在跨域的題目,axios 就會用回 XMLHttpRequest 對象舉行數據要求,一切都恢復一般了,header、cookies、content-type、authentication 等內容都被準確通報到效勞端。

項目中 webpack.config.js 的設置

devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true,
    proxy: {
        '/api': {
            target: 'http://localhost:8081/myserver',
            pathRewrite: {
                '^/api': ''
            }
        }
    }
}

設置中指定了將 http://localhost:8081/myserver 效勞的位置代辦為當地前端效勞的 http://localhost:8080/api。比方須要讀取用戶信息的原要求是 http://localhost:8081/myserver/user/zhangsan,代辦后,就變成 http://localhost:8080/api/user/zhangsan

等於 /api 的前綴代表了效勞端,所以在運用 axios 時,須要對每一個效勞端要求都增添上 /api 的前綴;一般在項目開闢中,須要對數據要求組件 axios 舉行二次封裝,以到達一致設置默許參數,一致數據要求進口等目標,那末此時就只須要在二次封裝的文件里一致調解要求前綴即可。

不過,webpack 的 devServer.proxy 僅在開闢形式下可用,臨盆形式下沒法運用。開闢形式下,調試效勞能夠讀取 webpack.config.js 中的設置內容舉行及時代辦,而項目在布置到臨盆環境前,須要將工程舉行編譯轉換成靜態的 js 文件,沒有調試效勞的支持天然是沒法舉行要求代辦的。

nginx 設置

雖然 devServer.proxy 的功用僅能事情於開闢形式,那末在臨盆形式下,天然也是有處理計劃的;一般 Vue 的項目在編譯成終究的 js 文件后,僅須要靜態效勞器即可,這个中又以 nginx 為最優挑選計劃,輕量、高性能、高併發、反向代辦效勞等均為其長處,這裏須要做的數據要求代辦的功用就運用到了 nginx 的 反向代辦 功用

conf/nginx.conf 文件設置增添以下內容

location /api/ {
    proxy_pass http://localhost:8081/myserver/;
}

該設置同樣是將 http://localhost:8081/myserver/ 的目標效勞端位置代辦為當地效勞的 /api 途徑,云云,臨盆環境下的數據要求題目也得以處理

個人原創內容,轉載請申明出處

完整內容:https://github.com/TerryZ

    原文作者:TerryZeng
    原文地址: https://segmentfault.com/a/1190000015318567
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞