开启掘金成长之旅!这是我参与「掘金日新计划 · 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去掉后,就不会自动展开啦,这肯定不是解决办法,具体有以下两种方式去解决。
- 通过变量控制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兼容不仅仅是上述这些,学习之路永远都是任重而道远!