IE兼容问题

255 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

前言

虽然IE已经淹没在历史的洪流中,但总有一些项目还是不得不去兼容IE11,比如一些银行项目。不兼容主要是浏览器之间内核不相同,一些规则也就不用,所以当兼容需要考虑很多方面,这里我们可以大致把兼容样式,方法,组件样式等方面。接下来我也会从这几个方面入手,总结一下常见的兼容方法,尽可能附带一下产生原因,帮助大家理解。

判断IE浏览器

首先,我们是针对ie做的兼容,那么第一步我们要知道当前浏览器是不是IE浏览器,我们可以定义一个方法去判断

 function IEVersion() {
  const userAgent = navigator.userAgent //取得浏览器的userAgent字符串
  const isIE =
    userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 //判断是否IE<11浏览器
  const isEdge = userAgent.indexOf('Edge') > -1 && !isIE //判断是否IE的Edge浏览器
  const isIE11 =
    userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1
  if (isIE) {
    const reIE = new RegExp('MSIE (\\d+\\.\\d+);')
    reIE.test(userAgent)
    const fIEVersion = parseFloat(RegExp['$1'])
    if (fIEVersion == 7) {
      return 7
    } else if (fIEVersion == 8) {
      return 8
    } else if (fIEVersion == 9) {
      return 9
    } else if (fIEVersion == 10) {
      return 10
    } else {
      return 6 //IE版本<=7
    }
  } else if (isEdge) {
    return 'edge' //edge
  } else if (isIE11) {
    return 11 //IE11
  } else {
    return -1 //不是IE浏览器
  }
}

如上,当返回值为-1的时候,就不是ie浏览器,在其他页面就可以通过该方法去判断是否是IE浏览器,我们也可以进一步去写一个函数直接返回true或false

export function isIE() {
  return IEVersion() !== -1
}

webpack

在ie中一些语法如es6的不支持会报错,这时候在打包过程中需要重新编译来支持ie浏览器,如果用webpack打包需要设置transpileDependencies,将需要重新编译的依赖放进去:

   // 重新编译elementUI代码,兼容ie
  transpileDependencies: [
    /[\\/]node_modules[\\/]_?(element-ui)(.*)/
  ]

css兼容

normalize.css

因为浏览器之间默认样式存在着一定的差异,首先我们需要抹平一些差异,这里我们可以用normalize.css,直接在项目中下载并且引入到main.ts当中即可

//npm
npm install normalize.css
//yarn
yarn add normalize.css

常见样式

flex:1

我们在写样式的时候,会通过flex:1让元素自适应剩余,在chrome中这样子写是没有问题的,chrome浏览器会解析成flex:1,1,0%,正常显示,但是在IE中会被解析成flex:1,1,0px,导致我们创建的元素没有高度,这个时候我们需要给当前元素加上固定的高度,这样子才会出来。

conent属性

我们经常用content属性在跟伪类选择器:after、:before使用去生成一些内容,后面还可以跟img图片地址,来填充空白,有点类似于我们的背景图片,当在IE中不管用的时候,我们可以用background去代替,将其当成背景图片来处理。

光标问题

在IE中,我们可能获取不到光标,接下里可以获取inputDOM元素,循环列表给每个input框设置unselectable属性为'on'

 const inputList = document.querySelectorAll('input[readonly="readonly"]')
    inputList.forEach(input => {
      input.setAttribute('unselectable', 'on')
    })

element-ui

el-cascader下拉框自动展开

在IE浏览器el-cascader会自动展开,主要是因为filterable属性影响的,当我们把filterable去掉后,就不会自动展开啦,这肯定不是解决办法,具体有以下两种方式去解决。

  1. 通过变量控制filterable属性,首先我们可以定义一个'userFilterable',初始值为false,当用户点击级联框的时候再将其设置为true,我们利用visible-change事件来控制值的改变。
       <el-cascader
          v-model="vlaue"
          :filterable="userFilterable"
          @visible-change="handleVisibleUserChange"
        ></el-cascader>
 data(){
   return{
    userFilterable:false
   }
 }
 methods:{
 handleVisibleUserChange(val) {
    if (val) {//val为true 下拉框显示 为false 下拉框隐藏
      this.userFilterable = true
    } else {
      this.userFilterable = false
    }
  }
 }

2.利用toggleDropDownVisible方法‘手动’收回。通过vue中$refs获取该方法,设置为false即可。

// this.$nextTick(() => {
      //   // 避免 ie浏览器自动展开选项面板
      //   ;(this.$refs.cascader as any).toggleDropDownVisible(false)
      // })

el-date-picker

在IE浏览器下如果我们的el-data-picker有默认值,那么我们会发现清空按钮不管用。这是因为start-placeholder、end-placeholder有值导致的,所以我们可以用两个变量控制,当有默认值的时候,将其设置为空

  <el-date-picker
    v-model="model"
    :start-placeholder="startPlaceholder"
    :end-placeholder="endPlaceholder"
    range-separator="~"
  ></el-date-picker>
 data() {
    return {
      model:'',
      startPlaceholder: '',
      endPlaceholder: ''
      },
 mounted() {
     if (!this.model && !this.model.length) {
         // 修复ie下,带有初始化时间,clear按钮无法清除时间的问题
        this.startPlaceholder = '开始日期'
        this.endPlaceholder = '开始日期'
      } 
  }

方法

缓存问题

有些时候,我们在IE中发现数据不更新,就是没有缓存结果,这时我们需要设置一下请求头

// 不缓存结果 解决IE刷新列表无数据更新
    config.headers['cache-control'] = 'no-cache'
    config.headers['Pragma'] = 'no-cache'

乱码问题

在IE下载文件会出现乱码问题,这个其实需要后端同事配合去处理,但我们还是得判断一下,如果是IE浏览器就需要用IE的方法去下载文件,通过window.navigator.msSaveBlob方法去判断:

// 兼容IE
  if (window.navigator.msSaveBlob) {
    try {
      window.navigator.msSaveBlob(new Blob([content]), filename as string)
    } catch (e) {
      console.log(e)
    }
    return
  }

总结

IE兼容确实不是容易的工作,当我们兼容IE的时候,不知道会有多少的坑等着我们去填,只能安慰自己踩了一下坑,就能长下记性。当然IE兼容不仅仅是上述这些,学习之路永远都是任重而道远!