由於開發的網頁須要嵌入到別的業務方的系統中,而使用該系統的人大多使用的是IE8,故項目須要兼容IE8。原本使用vue早早就開發好了,後來聽聞必須兼容IE8,故使用了支持 IE8 且有好多現成的表單組件的 layui 框架,而本身又已經習慣寫 ES6 的語法,因此引入了babel + webpack4來編譯打包。開發過程中,除了邊參考layui官網邊寫代碼,更讓人噁心的是 IE8 下出現的一些奇奇怪怪的問題,在此記錄下。javascript
未搞清楚webpack中 devServer.proxy
的用法css
參考: webpack中devServer.proxy的使用方式vue
低版本ie把 default
列爲關鍵字java
參考:Webpack4+Babel7+ES6兼容IE8webpack
其中 @babel/plugin-transform-runtime
這個plugin配置不須要配。web
如圖中laytpl.js 的 t.pt.parse
的 replace(/(?="|')/g, "\\")
這一步,在測試demo中動態生成的時候這裏運行後兩個雙引號之間 ""
是會變成 \"\"
,因此 <option value="">
會變成<option value=\"\">
,而在本身項目中一樣的代碼,在 IE8 下會被編譯成 <option value=\"">
,這樣致使編譯錯誤,報以下錯誤。瀏覽器
懷疑是由於打包後的 replace
方法被改寫了仍是啥,在瀏覽器運行這個項目的代碼後,在瀏覽器控制檯使用 replace 方法都會有問題,而不運行這個項目的代碼則沒有問題。bash
<option value="">請選擇</option>
中 value=""
改爲 value
,即不寫雙引號的空字符串。可是這樣又會引起另外一個問題,當選擇這個默認的」請選擇「的時候,此時value值會爲」請選擇「而致使出錯,以下圖。<option value="">請選擇</option>
中的雙引號改成單引號便可,這個是最佳方式。IE8 下監聽 propertychange
時,若在處理事件中給該 input 賦值,則又會致使觸發這個事件,從而形成死循環。babel
參考: IE8下propertychange事件引起的棧溢出app
$("#idname").bind("input propertychange", function() {
// 增長一個全局的同步信號,防止在ie8下陷入死循環
if($.syncProcessSign) return ;
$.syncProcessSign = true;
//函數執行...
$.syncProcessSign = false;
});
複製代碼
天性使然
::before
改成 :before
由於要將以上傳的文件的名字顯示在頁面上,故每次選擇文件後上傳文件前須要讀取到所選文件的 name,以下圖1所示,file的name實際上是能夠獲取的,可是在 ie8/9下不支持 obj.preview
方法,且ie8/9下是讀取不到所選文件的具體信息的,只能上傳後讀取file input 的value值,以下圖2所示
分環境來上傳,當爲非IE8/9時,採用 obj.preview
方法,並手動上傳(由於在上傳前要作校驗,好比校驗目前已上傳的數量是否超過限制,以及上傳的文件大小是否超過最大值);當爲IE8/9時,設置爲自動上傳(由於此時不能獲取到選中的file,手動上傳的 obj.upload(index, file)
須要具體file參數),從 file input 的value中讀取文件名並保存下來,上傳成功後再動態渲染出文件名,大體代碼以下:
let uploadInst = upload.render({
elem: "#uploadFile", //綁定元素
url: "/xxx/xxx", //上傳接口
accept: "file",
data: { sso },
auto: isIE8_9 ? true : false,
size: 1024 * MAX_FILE_SIZE_MB,
choose: function(resultObj) {
if (uploadFileList.length >= LIMIT_FILE_COUNT) {
layer.msg(`最多支持上傳${LIMIT_FILE_COUNT}個文件`);
if (!isIE8_9) {
// 若是是IE8/IE9,直接return掉
return;
}
}
if (!isIE8_9) {
//預讀本地文件,若是是多文件,則會遍歷。(不支持ie8/9)
resultObj.preview(function(index, file) {
crtFileInfo = { file: file }; // 保存當前上傳的文件信息
resultObj.upload(index, file); //文件上傳
});
} else {
let inputFile = $('input[type="file"]');
let fileValue = inputFile[0].value;
let pos = fileValue.lastIndexOf("\\");
let fileName = fileValue.substring(pos + 1);
crtFileInfo = { file: { name: fileName } }; // 保存當前上傳的文件名
}
},
before: function(obj) {
//obj參數包含的信息,跟 choose回調徹底一致
layer.load(); //上傳loading
},
done: function(res) {
//上傳完畢回調
console.log("file上傳完畢");
if (isIE8_9 || isIE10Func()) {
resetUploadInput(); // 重置file input,否則在低版本ie下不能重複上傳
}
if (res.code === "0000") {
crtFileInfo && (crtFileInfo.id = res.data);
uploadFileList.push(crtFileInfo);
} else {
layer.msg(res.message);
}
crtFileInfo = null;
layer.closeAll("loading"); //關閉loading
// 渲染已上傳文檔區域
renderFileList();
},
error: function() {
//請求異常回調
crtFileInfo = null;
console.log("上傳文件失敗");
layer.closeAll("loading"); //關閉loading
}
});
複製代碼
由於此時file input 的value值跟上一個文件名是同樣的,這樣input會認爲沒有發生變化,故不會被喚起。
在 done
回調中,清除input的value值。IE8下沒法改變input的value值,IE9/10能夠,layui在IE8下的file input 外層包了一個form,此時reset form便可,大體代碼以下:
// 處理因ie形成的沒法上傳同名文件
function resetUploadInput() {
const $fileInputEle = $(".layui-upload-file")
const $fileUploadFormEle = $('.layui-upload-form')[0];
if(isIE8Func()){
$fileUploadFormEle.reset();
}else if(isIE9Func() || isIE10Func()){
$fileInputEle.attr("type", "hidden");
$fileInputEle.attr("type", "file");
}
}
複製代碼
由於文件列表的每一個文件的index寫在了dataset裏,而低版本ie不支持 dataset
。
// 兼容dataset
export const getDataset = function(ele) {
if (ele.dataset) {
return ele.dataset;
} else {
var attrs = ele.attributes, //元素的屬性集合
dataset = {},
name,
matchStr;
for (var i = 0; i < attrs.length; i++) {
//是不是data- 開頭
matchStr = attrs[i].name.match(/^data-(.+)/);
if (matchStr) {
//data-auto-play 轉成駝峯寫法 autoPlay
name = matchStr[1].replace(/-([\da-z])/gi, function(all, letter) {
return letter.toUpperCase();
});
dataset[name] = attrs[i].value;
}
}
return dataset;
}
};
複製代碼
在低版本ie下,若不打開瀏覽器控制檯,console會不存在,致使console.log()報錯。
// 憨憨的方式
if(console && console.log){
console.log('test');
}
複製代碼
1/**
2 * 解析URL傳參
3 * @param {*} key
4 */
5
6export const getQueryString = function(key) {
7 let after = window.location.search;
8 if (location.href.indexOf("?") === -1) return null; //若是url中沒有傳參直接返回空
9
10 //key存在先經過search取值若是取不到就經過hash來取
11 after = after.substr(1) || window.location.hash.split("?")[1];
12 if (after) {
13 let reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)");
14 let r = after.match(reg);
15 if (r != null) {
16 return decodeURIComponent(r[2]);
17 } else {
18 return null;
19 }
20 }
21};
複製代碼
1function downloadFile($, url, params) {
2 // Build a form
3 var form = $("<form></form>")
4 .attr("action", url)
5 .attr("method", "post");
6 // Add the one key/value
7 $.each(params, function(k, v) {
8 form.append(
9 $("<input></input>")
10 .attr("type", "hidden")
11 .attr("name", k)
12 .attr("value", v)
13 );
14 });
15 //send request
16 form
17 .appendTo("body")
18 .submit()
19 .remove();
20}
複製代碼