使用layui + es6 + webpack4开发

因为开发的网页需要嵌入到别的业务方的系统中,而使用该系统的人大多使用的是IE8,故项目需要兼容IE8。本来使用vue早早就开发好了,后来听闻必须兼容IE8,故使用了支持 IE8 且有好多现成的表单组件的 layui 框架,而自己又已经习惯写 ES6 的语法,所以引入了babel + webpack4来编译打包。开发过程当中,除了边参考layui官网边写代码,更让人恶心的是 IE8 下出现的一些奇奇怪怪的问题,在此记录下。

出现的问题以及解决方式

webpack代理发送请求

出现原因

未搞清楚webpack中 devServer.proxy 的用法

解决方式

参考: webpack中devServer.proxy的使用方式

ie8下出现SCRIPT1010 缺少标识符

出现原因

低版本ie把 default 列为关键字

解决方式

参考: Webpack4+Babel7+ES6兼容IE8

其中 @babel/plugin-transform-runtime 这个plugin配置不需要配。

ie8下select动态渲染的问题

出现原因

如图中laytpl.js 的 t.pt.parse 的 replace(/(?="|')/g, "\") 这一步,在测试demo中动态生成的时候这里运行后两个双引号之间 "" 是会变成 "" ,所以 <option value=""> 会变成 <option value=\"\"> ,而在自己项目中同样的代码,在 IE8 下会被编译成 <option value=\""> ,这样导致编译错误,报如下错误。

怀疑是因为打包后的 replace 方法被改写了还是啥,在浏览器运行这个项目的代码后,在浏览器控制台使用 replace 方法都会有问题,而不运行这个项目的代码则没有问题。

解决方式

  1. <option value="">请选择</option>value="" 改成 value ,即不写双引号的空字符串。但是这样又会引发另一个问题,当选择这个默认的”请选择“的时候,此时value值会为”请选择“而导致出错,如下图。
  2. <option value="">请选择</option> 中的双引号改为单引号即可,这个是最佳方式。

ie8下监听input导致堆栈溢出

出现原因

IE8 下监听 propertychange 时,若在处理事件中给该 input 赋值,则又会导致触发这个事件,从而造成死循环。

解决方式

参考: IE8下propertychange事件引发的栈溢出

1$("#idname").bind("input propertychange", function() {
2  // 增加一个全局的同步信号,防止在ie8下陷入死循环
3    if($.syncProcessSign) return ;
4        $.syncProcessSign = true;
5       //函数执行...
6    $.syncProcessSign = false;
7});
复制代码

ie8不支持before等伪元素

出现原因

天性使然

解决方式

参考: css IE8的兼容性问题

::before` 改为 `:before
复制代码

ie8下上传文件的问题

出现原因

因为要将以上传的文件的名字显示在页面上,故每次选择文件后上传文件前需要读取到所选文件的 name,如左图所示,file的name其实是可以获取的,但是在 ie8/9下不支持 obj.preview 方法,且ie8/9下是读取不到所选文件的具体信息的,只能上传后读取file input 的value值,如右图所示

解决方式

参考: layui.upload上传文件或图片在before执行上传前阻止停止上传

在IE8下使用layui遇到的坑

分环境来上传,当为非IE8/9时,采用 obj.preview 方法,并手动上传(因为在上传前要做校验,比如校验目前已上传的数量是否超过限制,以及上传的文件大小是否超过最大值);当为IE8/9时,设置为自动上传(因为此时不能获取到选中的file,手动上传的 obj.upload(index, file) 需要具体file参数),从 file input 的value中读取文件名并保存下来,上传成功后再动态渲染出文件名,大致代码如下:

1let uploadInst = upload.render({
 2  elem: "#uploadFile", //绑定元素
 3  url: "/xxx/xxx", //上传接口
 4  accept: "file",
 5  data: { sso },
 6  auto: isIE8_9 ? true : false,
 7  size: 1024 * MAX_FILE_SIZE_MB,
 8  choose: function(resultObj) {
 9    if (uploadFileList.length >= LIMIT_FILE_COUNT) {
10      layer.msg(`最多支持上传${LIMIT_FILE_COUNT}个文件`);
11      if (!isIE8_9) {
12        // 如果是IE8/IE9,直接return掉
13        return;
14      }
15    }
16
17    if (!isIE8_9) {
18      //预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
19      resultObj.preview(function(index, file) {
20        crtFileInfo = { file: file }; // 保存当前上传的文件信息
21        resultObj.upload(index, file); //文件上传
22      });
23    } else {
24      let inputFile = $('input[type="file"]');
25      let fileValue = inputFile[0].value;
26      let pos = fileValue.lastIndexOf("\\");
27      let fileName = fileValue.substring(pos + 1);
28      crtFileInfo = { file: { name: fileName } }; // 保存当前上传的文件名
29    }
30  },
31  before: function(obj) {
32    //obj参数包含的信息,跟 choose回调完全一致
33    layer.load(); //上传loading
34  },
35  done: function(res) {
36    //上传完毕回调
37    console.log("file上传完毕");
38    if (isIE8_9 || isIE10Func()) {
39      resetUploadInput(); // 重置file input,不然在低版本ie下不能重复上传
40    }
41
42    if (res.code === "0000") {
43      crtFileInfo && (crtFileInfo.id = res.data);
44      uploadFileList.push(crtFileInfo);
45    } else {
46      layer.msg(res.message);
47    }
48    crtFileInfo = null;
49    layer.closeAll("loading"); //关闭loading
50    // 渲染已上传文档区域
51    renderFileList();
52  },
53  error: function() {
54    //请求异常回调
55    crtFileInfo = null;
56    console.log("上传文件失败");
57    layer.closeAll("loading"); //关闭loading
58  }
59});
复制代码

ie8/9/10下再次上传同一文件时,选择文件不会被唤起

出现原因

因为此时file input 的value值跟上一个文件名是一样的,这样input会认为没有发生变化,故不会被唤起。

解决方式

参考: fly.layui.com/jie/43990/

done 回调中,清除input的value值。IE8下无法改变input的value值,IE9/10可以,layui在IE8下的file input 外层包了一个form,此时reset form即可,大致代码如下:

1  // 处理因ie造成的无法上传同名文件
 2  function resetUploadInput() {
 3    const $fileInputEle = $(".layui-upload-file")
 4    const $fileUploadFormEle = $('.layui-upload-form')[0];
 5    if(isIE8Func()){
 6      $fileUploadFormEle.reset();
 7    }else if(isIE9Func() || isIE10Func()){
 8      $fileInputEle.attr("type", "hidden");
 9      $fileInputEle.attr("type", "file");
10    }
11  }
复制代码

ie8/9/10删除上传的文件报错

出现原因

因为文件列表的每个文件的index写在了dataset里,而低版本ie不支持 dataset

解决方式

1// 兼容dataset
 2export const getDataset = function(ele) {
 3  if (ele.dataset) {
 4    return ele.dataset;
 5  } else {
 6    var attrs = ele.attributes, //元素的属性集合
 7      dataset = {},
 8      name,
 9      matchStr;
10    for (var i = 0; i < attrs.length; i++) {
11      //是否是data- 开头
12      matchStr = attrs[i].name.match(/^data-(.+)/);
13      if (matchStr) {
14        //data-auto-play 转成驼峰写法 autoPlay
15        name = matchStr[1].replace(/-([\da-z])/gi, function(all, letter) {
16          return letter.toUpperCase();
17        });
18        dataset[name] = attrs[i].value;
19      }
20    }
21    return dataset;
22  }
23};
复制代码

常用的工具类方法

解析URL传参

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};
复制代码

使用post方式实现文件下载

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}
复制代码
我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章