使用layui + es6 + webpack4开发

项目背景

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

出现的问题以及解决方式

webpack代理发送请求

出现缘由

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

解决方式

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

ie8下出现SCRIPT1010 缺乏标识符

出现缘由

低版本ie把 default 列为关键字java

解决方式

参考:Webpack4+Babel7+ES6兼容IE8webpack

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

ie8下select动态渲染的问题

出现缘由

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

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

image.png

image.png

解决方式

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

image.png

image.png

ie8下监听input致使堆栈溢出

出现缘由

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

解决方式

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

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

ie8不支持before等伪元素

出现缘由

天性使然

解决方式

参考:css IE8的兼容性问题

::before 改成 :before

ie8下上传文件的问题

出现缘由

由于要将以上传的文件的名字显示在页面上,故每次选择文件后上传文件前须要读取到所选文件的 name,以下图1所示,file的name实际上是能够获取的,可是在 ie8/9下不支持 obj.preview 方法,且ie8/9下是读取不到所选文件的具体信息的,只能上传后读取file input 的value值,以下图2所示

image.png
image.png

解决方式

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

在IE8下使用layui遇到的坑

分环境来上传,当为非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,直接returnreturn;
      }
    }

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

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便可,大体代码以下:

// 处理因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");
    }
  }
复制代码

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

出现缘由

由于文件列表的每一个文件的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对象致使的报错

出现缘由

在低版本ie下,若不打开浏览器控制台,console会不存在,致使console.log()报错。

解决方式

// 憨憨的方式
if(console && console.log){
    console.log('test');
}
复制代码

经常使用的工具类方法

解析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}
复制代码
相关文章
相关标签/搜索