IE9兼容爬坑總結—vuecli3+eleUI後臺管理項目兼容IE9

Q1. 不兼容ES6語法

引入babel-polyfill和es6-promise兩個插件,將ES6語法轉化爲ES5javascript

1-一、安裝

cnpm install --save-dev babel-polyfill es6-promise
複製代碼

1-二、main.js引入

// 解決低版本瀏覽器不支持promise問題
import 'babel-polyfill'
import Es6Promise from 'es6-promise'
Es6Promise.polyfill()
複製代碼

在配置文件vue.config.js中引入

// ...省略
chainWebpack: config => {
    // 新增
    config.entry.app = ['babel-polyfill', './src/main.js']
}
// ...省略
複製代碼

Q2. CSS Hack

不可能爲了兼容一個IE9,而下降了其它主流版本瀏覽器下的頁面體驗,因此我會使用CSS Hack,在IE9時再去加載兼容文件和佈局。css

CSS hack是經過在CSS樣式中加入一些特殊的符號,讓不一樣的瀏覽器識別不一樣的符號,以達到應用不一樣的CSS樣式的目的 html

2-一、條件註釋法

由於我是針對IE9,因此我採用了IE瀏覽器專有的Hack方式:條件註釋法。前端

2-1.一、在public目錄建立文件夾ie9

主要用來存放爲了兼容ie9而添加的css和js補丁文件等vue

2-1.二、在ie9文件下建立css文件ie9.css

ie9樣式補丁文件java

2-1.三、在index.html的head中引入
<head>
    // ...
    <!--[if lte IE 9]> <link href="./ie9/ie9.css" rel="stylesheet"></link> <![endif]-->
</head>
複製代碼

這樣作了以後,在瀏覽器是ie9時,會自動加載ie9.css文件,而在其餘瀏覽器下則會忽略這行代碼ios

Q3. 不兼容flex佈局

巧用position、float、display:inline-block屬性靈活修改佈局git

Q4. 不兼容背景顏色的漸變寫法background: linear-gradient(...)

正常:es6

background: linear-gradient(180deg, #1A74E4, #2599F0);
複製代碼

ie9兼容寫法:github

filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#1A74E4, endColorstr=#2599F0);
-ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=1, startColorstr=#1A74E4, endColorstr=#2599F0)";
複製代碼

Q五、el-table數據量多(頁面有滾動條時)在ie中會致使頁面卡頓

緣由:包裹表格的容器用了絕對或者相對定位,通常就是.el-table用了相對定位,但沒有設置層級,在ie中z-index層級下降。

解決方法:只須要將表格所屬的父級或者祖父容器的z-index調高就行,將.el-table設置爲10以後,卡頓問題解決

Q六、不支持placeholder

用了一個大佬封裝的js,稍微改了一下,能支持正常狀況下placeholder的顯示,好比登陸註冊頁。

6-一、 在工具類文件夾下生成brower-version.js文件,用來判斷瀏覽器版本

brower-version.js:

export default function browerVersion() {
  var ua = navigator.userAgent
  var ver = 0
  var versiondata
  var versionbool

  if (ua) {
    if (ua.match(/MSIE\s+([\d]+)\./i)) {
      ver = RegExp.$1
    } else if (ua.match(/Trident.*rv\s*:\s*([\d]+)\./i)) {
      ver = RegExp.$1
    }
  }

  versiondata = parseInt(ver)

  if (versiondata <= 9 && versiondata !== 0) {
    versionbool = true
  } else {
    versionbool = false
  }

  // versionbool true: 低於ie9 false: ie10+
  return versionbool
}
複製代碼

6-二、定義全局的瀏覽器是不是ie9版本的判斷字段

main.js

import browerVersion from '@/assets/utils/brower-version.js'
const isIE9 = browerVersion()
Vue.prototype.$browerVersion = isIE9
複製代碼

6-三、工具類文件夾下建立ie-placeholder.js文件

/assets/utils/ie-placeholder.js

6-四、項目加載時就load一遍placeholder定義文件,爲ie9下的input輸入框加上placeholder

在App.js調用ie-placeholder.js定義的方法 初始化各input的placeholder

<script>
import iePlaceholders from '@/assets/utils/ie-placeholder'
export default {
  name: 'App',
  mounted() {
    if (this.$browerVersion) {
      iePlaceholders()
    }
  }
}
</script>
複製代碼

可是涉及到elementUI的其餘組件,好比日期選擇,好比級聯選擇,就會有點問題。這裏的建議仍是在ie9下不要糾結顯示placeholder,體驗太差了。

Q七、輸入框自帶有文本刪除按鈕和密碼查看按鈕

在ie10+的版本咱們能夠經過

::-ms-clear,
::-ms-reveal{
  display:none !important;
}
複製代碼

這段代碼來隱藏,可是我發如今ie9下面是沒用的。只能經過在輸入框末尾增長一個和背景同色的塊來遮掉,可是這樣會影響輸入的內容的全顯示,個人作法是就讓它留着,影響不大。

Q八、input不支持type=number

當input的type屬性爲number時,仍是能夠任意輸入其餘符號。。我選擇在ie9放棄number限制的掙扎

Q九、el-upload沒法使用

在ie9下,el-upload是沒法使用的。我引入了可以兼容ie9的其餘上傳插件,當瀏覽器爲ie9時就用自定義的上傳組件,當非ie9時就保持原來的el-upload組件。

用vue-upload-component替代el-upload

9-一、安裝vue-upload-component

cnpm install vue-upload-component --save
複製代碼

9-二、引入

能夠全局引入也能夠局部引入,由於我只有兩個地方用到了上傳組件,因此我選擇在用到的頁面引入。

<template>
<!-- 省略n行代碼 -->
<file-upload
    v-if="$browerVersion"
    ref="compatibleUpload"
    v-model="compatibleFiles"
    :post-action="`${API.UploadImg}`"
    @input-file="inputFile"
>
    <el-button
       :loading="uploadLoading"
       :icon="imgName ? '' : 'el-icon-upload2'"
       :title="imgName ? '從新選擇' : '選擇圖片'"
        plain
    >
          {{ !imgName ? '上傳圖片' : imgName }}
    </el-button>
</file-upload>
<!-- 省略n行代碼 -->
</template>
<script>
import VueUploadComponent from 'vue-upload-component'
export default {
  components: {
    FileUpload: VueUploadComponent
  },
  data() {
      imgSizeLimit: 2,
      imgName: '',
      imgUrl: '',
      uploadLoading: false,
      compatibleFiles: []
  },
  methods: {
      inputFile(newFile, oldFile, prevent) {
      // 添加文件
      if (newFile && !oldFile) {
        // 過濾不是圖片後綴的文件
        if (!/\.(jpg|png)$/i.test(newFile.name)) {
          this.$message.closeAll()
          this.$message.warning('只能上傳jpg/png文件,請從新選擇')
          return prevent
        }
        if (newFile.size > this.imgSizeLimit * 1024 * 1024) {
          this.$message.closeAll()
          this.$message.warning(`上傳的圖片的大於${this.imgSizeLimit}M,請從新選擇`)
          return prevent
        }
        // 自動上傳
        if (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) {
          if (!this.$refs.compatibleUpload.active) {
            this.uploadLoading = true
            this.$refs.compatibleUpload.active = true
          }
        }
      }

      // 上傳完成
      if (newFile && oldFile && !newFile.active && oldFile.active) {
        // 得到相應數據
        this.uploadLoading = false
        this.$refs.compatibleUpload.remove(newFile) // 刪除當前文件對象
        let response = newFile.response
        if (Object.prototype.toString.call(response) !== '[object Object]') {
          response = (new Function('return ' + response))()
        } else {
          this.$message.closeAll()
          this.$message.error('圖片上傳失敗, 請從新上傳')
        }
        if ((response.resultCode === '1' || response.resultCode === 1) && response.data) {
          this.imgUrl = response.data
          this.imgName = newFile.name
          this.$message.closeAll()
          this.$message.success('圖片上傳成功')
        } else {
          this.imgUrl = ''
          this.imgName = ''
          this.$message.closeAll()
          let errorMsg = response.resultMessage ? response.resultMessage : '圖片上傳失敗, 請從新上傳'
          if (['10021'].includes(response.resultCode)) {
            errorMsg = `上傳的圖片的大於${this.imgSizeLimit}M,請從新選擇`
            this.$message.warning(errorMsg)
            return
          }
          this.$message.error(errorMsg)
        }
      }
    }
  }
}
</script>
複製代碼

具體用法請參考官方文檔,這要注意若是讓組件本身發起請求,就是使用post-action參數,則是用iframe模擬form表單提交數據的,用這種方式傳給後臺的數據就是formData格式,可是不能添加header請求頭。若是非要有請求頭,那就要使用custom-action自定義上傳方法,可是自定義上傳方法的話,接口參數就不能用formData格式來傳給後臺了,爲啥?由於ie9不支持new FormData()。。

Q十、不支持JSON.parse

沒錯,在IE9如下是不支持JSON.parse方法來解析json字符串的,有兩種方法來替代JSON.parse

10-一、eval方式

function strToJson(str){ 
    var json = eval('(' + str + ')'); 
    return json; 
} 
複製代碼

可是出於安全性的考慮,建議儘可能不要使用eval,若是從第三方獲取數據進行解析,會存在惡意腳本代碼的風險。

10-二、new Function方式

function strToJson(str){ 
    var json = (new Function("return " + str))(); 
    return json; 
} 
複製代碼

Q十一、vue項目在IE中自動讀取緩存中的數據,不從新發請求

這也不算只是ie9的問題了,ie內核都存在這個問題。當你請求接口時,請求地址和請求參數都沒有變化的時候,ie是會默認從緩存中獲取數據而不會從新發送請求的。

只要保證咱們每次的請求都是一個新的請求,就能夠避免這種狀況了,最簡單的方式就是每次請求都帶多一個時間戳參數,只須要在axios攔截器添加幾行設置時間戳參數的代碼便可

// request攔截器
service.interceptors.request.use(
  config => {
    const time = Date.parse(new Date()) / 1000
    // 添加時間戳參數
    if (config.method === 'post') {
      config.data = {
        ...config.data,
        t: time
      }
    }
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        t: time
      }
    }
    return config
  },
  error => {
    // Do something with request error
    return Promise.reject(error)
  }
)
複製代碼

Q十一、在文本框中進行刪除操做時,文本框的value不更新。

在咱們以前Q2建立的ie9文件夾下,新建ie9-oninput-polyfill.js文件

11-一、ie9-oninput-polyfill.js:

/* eslint-disable */
(function (d) {
  if (navigator.userAgent.indexOf('MSIE 9') === -1) return;

  d.addEventListener('selectionchange', function() {
    var el = d.activeElement;

    if (el.tagName === 'TEXTAREA' || (el.tagName === 'INPUT' && el.type === 'text')) {
      var ev = d.createEvent('CustomEvent');
      ev.initCustomEvent('input', true, true, {});
      el.dispatchEvent(ev);
    }
  });
})(document);
複製代碼

11-二、在css Hack中引入

<head>
    // ...
    <!--[if lte IE 9]> <link href="./ie9/ie9.css" rel="stylesheet"></link> <script src="./ie9/ie9-oninput-polyfill.js" type="text/javascript"></script> <![endif]-->
</head>
複製代碼

Q十二、不能導出二進制文件流

由於ie9一下不支持new Blob,因此不能將二進制文件流轉爲文件下載。解決方法是讓後臺改接口,不要傳二進制文件流過來,直接給前端傳文件下載連接

Q1三、ie9下el-table的排序三角形錯位

解決方法:

.el-table .caret-wrapper {
  display: inline-block;
}
.el-table .sort-caret{
  display: block;
}
複製代碼

好了,暫時只想到這些,後續有遺漏的會繼續補充~

相關文章
相關標籤/搜索