某天,某測試說:“這個頁面在 ie8 下白屏,9也白。。”
某前端開發: 吭哧吭哧。。。一上午的時間就過去了,搞定了。
第二天,某測試說:“ie 又白了。。”
某前端開發: 吭哧吭哧。。。誰用的 <code>object.assign</code>,出來我保證削不屎你。
原諒我不禁又黑了一把 ie。
有人可能會想,都要淘汰了,還有什麼好講的?
也許幾年後,确實沒用了,但目前我們的系統還是要對 ie8+ 做相容,因為确實還有個别使用者,盡管他沒朋友。。。
記錄下本次在 ie 下踩得坑,讓後面的同學能夠不再在這上面浪費時間了。
首先,看下面代碼(以下測試在 ie9)
這段代碼跑的妥妥的,沒什麼問題。
一般來說,babel 在轉換繼承時,可能會出現相容問題,那麼,再看這一段
這段代碼同樣也可以正常運作
也就是說在上述這兩種情況下,不做任何處理(前提是已經加載了 es5-shim/es5-sham),在 ie9 下都可以正常運作。
然後我們再看下會跑挂的代碼
這段代碼在進階浏覽器中是沒問題的,在 ie9 中會出現注釋所描述的問題
從這些問題分析,可得出3個結論
在構造函數裡的定義的屬性無法被繼承
在構造函數裡不能使用 <code>this.props.xx</code>
類屬性或方法是無法被繼承的
也就是說,隻要規避了這三個條件的話,不做任何處理(前提是已經加載了 es5-shim/es5-sham),在 ie9 下都可以正常運作。
第二點,是完全可以避免的,切記在 <code>constructor</code> 直接使用 <code>props.xxx</code>, 不要再用 <code>this.props.xxx</code> 第三點,也是可以完全避免的,因為從理論上來說,類屬性就不該被繼承,如果想使用父類的類屬性可以直接<code>test2.defaultprops = test.defaultprops;</code> 第一點,可避免,但無法完全避免
第一點,有時是無法完全避免的,那麼就要查詢原因,才能找到解決方案
我們把 babel 轉義後的代碼放出來就能查出原因了
通過上述的代碼注釋,可以得出有兩處問題需要解決
正确的擷取父類(解決無法繼承到在構造函數裡定義的屬性或方法)
正确的将子類的原型指向了父類(解決無法繼承到類屬性或方法)
通過文檔的查詢,發現隻要開啟 es2015-classes 的 loose 模式即可解決第一個問題
babel have two modes: a normal mode follows the semantics of ecmascript 6 as closely as possible. a loose mode produces simpler es5 code.
babel 有兩種模式:
盡可能符合 es6 語義的 normal 模式。
提供更簡單 es5 代碼的 loose 模式。
盡管官方是更推薦使用 normal 模式,但為了相容 ie,我們目前也隻能開啟 loose 模式。
在 babel6 中,主要是通過 babel-preset-2015 這個插件,來進行轉義的
我們看下 babel-preset-2015
是一堆對應轉義的插件,從命名上也可看出了大概,比如 babel-plugin-transform-es2015-classes 就是做類的轉義的,也就是我們隻需把它開啟 loose 模式,即可解決我們的一個問題
看下開啟了 loose 模式的代碼,你會發現它的确更接近 es5
但從我們團隊的 老司機 口中
剛好解決我們上述碰到的兩個問題
這個 <code>babel-plugin-transform-proto-to-assign</code> 插件會生成一個 _defaults 方法來處理原型
這個插件正确的将子類的原型指向了父類(解決無法繼承到類屬性或方法)
本文講述低版本浏覽器報錯的原因和解決方案
一方面是提示下在構造函數裡不要使用 <code>this.props.xx</code>
另一方面也對繼承的機制有了更好的了解
在這次項目中發現在低版本浏覽器跑不起來的兩點主要原因:
<code>script5007: 無法擷取屬性 xxx 的值,對象為 null 或未定義</code>,這種情況一般是元件繼承後,無法繼承到在構造函數裡定義的屬性或方法,同樣類屬性或方法也同樣無法繼承
<code>script438: 對象不支援 xxx 屬性或方法</code>,這種情況一般是使用了 es6、es7 的進階文法,<code>object.assgin</code> <code>object.keys</code> 等,這種情況在移動端的一些 ‘神機’ 也一樣會挂。
第一點本文已經分析,預知第二點講解請見下篇。
備注:下篇會主要介紹下如何讓 用了 <code>object.assign</code> 的那位同學可以繼續用,又不會被削。