Dva項(xiàng)目兼容性
之前上線的Dva項(xiàng)目,在Chrome和Safari中表現(xiàn)良好,但是在有些瀏覽器打不開,比如IE、某些版本的FireFox。這是由于在項(xiàng)目中,網(wǎng)絡(luò)請求模塊用到了fetch請求,由于fetch的局限性,導(dǎo)致部分瀏覽器不兼容?,F(xiàn)記錄下適配到IE的過程,以供自己學(xué)習(xí)。
Fetch
之前發(fā)現(xiàn)IE瀏覽器打不開,通過查詢得知是fetch的原因。由于一開始沒有關(guān)注過fetch請求,以為是dva框架自帶的請求框架,就沒有深入的學(xué)習(xí)。查詢一系列資料之后,將fetch的知識(shí)學(xué)習(xí)了一遍。
Fetch API 是基于 Promise 設(shè)計(jì),在你理解了Promise之后,F(xiàn)etch對于你來說并不困難,通過閱讀文檔很快就能學(xué)會(huì)。推薦推薦 MDN Fetch 教程 和 萬能的WHATWG Fetch 規(guī)范。由于舊的瀏覽器并不支持Promise,所以導(dǎo)致了Fetch的局限性。
Fetch原生支持率:

由此可見,F(xiàn)etch的兼容性并不好。不過網(wǎng)上給出了相應(yīng)的解決辦法,通過引入polyfill以支持IE8+
- 由于 IE8 是 ES3,需要引入 ES5 的 polyfill: es5-shim, es5-sham
- 引入 Promise 的 polyfill: es6-promise
- 引入 fetch 探測庫:fetch-detector
- 引入 fetch 的 polyfill: fetch-ie8
- 可選:如果你還使用了 jsonp,引入 fetch-jsonp
- 可選:開啟 Babel 的 runtime 模式,現(xiàn)在就使用 async/await
在嘗試了以上方法,把它們引入后,并沒有生效(不
Fetch 請求默認(rèn)是不帶 cookie 的,需要設(shè)置
fetch(url, {credentials: 'include'})
在實(shí)際操作的時(shí)候,加上了上述代碼,依然不能帶著cookie傳遞給后臺(tái)(不
這里只介紹fetch的最簡單應(yīng)用,更具體的應(yīng)用請看github
`post請求`
fetch(url, {
method: method,
body: formData,
}).then(checkStatus)
.then(parseJSON)
.then((data) => {
return { data };
})
.catch(err => ({ err }));
發(fā)起fetch請求,需要將參數(shù)轉(zhuǎn)化成FormData類型,請求成功后會(huì)依次執(zhí)行.then()函數(shù),在data中獲取后臺(tái)數(shù)據(jù)。
XMLHTTPRequest
各種引入polyfill仍然不能在IE中兼容,隨后將目光轉(zhuǎn)移到了原生js上。查看文檔發(fā)現(xiàn):所有現(xiàn)代瀏覽器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都內(nèi)建了 XMLHttpRequest 對象。
由于沒有用過jQuery和ajax,只是在查過文檔稍稍了解了一下用法(誤導(dǎo)
let xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
if (xhr) {
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200){
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send(paramstring);
}
雖然并不知道原理,但上述代碼在IE瀏覽器上運(yùn)行正常,可以正確的獲取到后臺(tái)的值。但是由于它時(shí)候在onreadystatechange屬性中,一直調(diào)用后面的方法,整個(gè)請求下來,調(diào)用五次后面的方法,在最后一次readyState等于4的時(shí)候,才獲取到值。而且值在回調(diào)函數(shù)中,不能直接賦值獲取,需要通過調(diào)用者傳遞一個(gè)回調(diào)函數(shù),將值回調(diào)出去。
由于項(xiàng)目中采用Promise回調(diào),并不想做太大改動(dòng),所以摒棄了這種寫法
Axios
Axios 是一個(gè)基于 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。
{% asset_img 68747470733a2f2f73617563656c6162732e636f6d2f6f70656e5f73617563652f6275696c645f6d61747269782f6178696f732e737667.svg Axios兼容性 %}
由上圖可知,axios兼容性十分不錯(cuò),寄希望它可以解決Dva項(xiàng)目的兼容性問題。用axios整體替換掉fetch。Axios API和Fetch API十分相近,簡單的用法和fetch基本一致:
`post請求`
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
然后在入口函數(shù)中引入es6-promise
require('es6-promise').polyfill();
經(jīng)本地測試,IE瀏覽器可以正常訪問,基本解決了IE兼容性的問題。
大致查看了一下文檔,axios的拓展性以及可定制性比較高,操作空間比fetch要強(qiáng),考慮后續(xù)將fetch都替換成axios
其他
- 在測試FireFox瀏覽器的時(shí)候,一直白屏??刂婆_(tái)報(bào)錯(cuò)
錯(cuò)誤:樣式表單index.css 未載入,因?yàn)樗腗IME類型 "text/html" 不是 "text/css"
在index.html中,將
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
改成
<!--[if IE]>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<![endif]-->
這樣,只有在IE下才會(huì)使用這個(gè)頭部聲明,而在FireFox下是不會(huì)使用的。
- 訪問項(xiàng)目,到某路由下刷新出現(xiàn)白屏并且出現(xiàn)如下錯(cuò)誤
index.js:1 Uncaught SyntaxError: Unexpected token <
在編譯之前將index.js的相對路徑改成絕對路徑、
/* <script src="index.js"></script> */
<script src="/index.js"></script>
index.css同理