由于开发的网页须要嵌入到别的业务方的系统中,而使用该系统的人大多使用的是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}
复制代码