使用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}
複製代碼
相關文章
相關標籤/搜索