原以为IE11下应该不会存在什么兼容问题,毕竟ie11也勉强算得上新时代的浏览器,但实际使用时,遇到的问题还不少!
问题1:打包后的代码中中出现了不识别的es6语法或其他新的js特性
范围:全局
解决方案:
首先查看报错的js文件,如果是 chunk-vendor 文件中的js语法错误,那么可以基本确定是由于依赖包中引入的代码为非es5代码引起的,由于线上代码为压缩后的代码,无法确定是哪个依赖包中使用ie不识别的代码,这时可以在本地使用此命令yarn build --mode=development
,打包获取一份未经过压缩的代码,其中包含具体引入的node_modules里的包的路径信息,然后再对比ie中报错的文件进行关键字搜索确定具体的依赖包报错,确认过后,将依赖包名称加入到vue.config.js
中的transpileDependencies
选项即可。
如果是其他chunk文件或者main.js等报错,一般则是代码中使用到了ie中不支持的一些新的js特性,自行找到相关代码更改即可。
例如我司项目中已经发现的不兼容的一些依赖,已经发现的不兼容的依赖包如下:
// vue.config.js
...
transpileDependencies:["vue-echarts-v3", "view-design", "elasticsearch"]
...
复制代码
view-design
也就是[email protected]
版本,其本身是提供了es5的代码了,但因为项目中有单独引入iview中的emitter工具函数,所以需要经babel处理。另外,如果是按需引入 iview的话,也需要经过babel转译为es5代码。
问题2:get请求传递中文参数乱码
范围:全局
复制代码
解决方案:
1). 对get的参数使用encodeURIComponent进行编码
2). 如果使用axios作为ajax请求,则把参数放入params中,而不是手动拼接,axios会自动编码
问题3:el-cascader在处于多选模式并且filterable为true时,会自动聚焦并弹出选择面板。
原因:在IE11下input的placeholder发生变化后会触发oninput事件(只要对input的placeholder设置就会触发,即便placeholder的值并没有发生变化)
范围:Element-UI中cascader组件
解决方案:
修改组件中的方法代码
import { Cascader } from 'element-ui';
const isIE = !isNaN(Number(document.documentMode));
if(isIE) {
Cascader.methods.handleInput = function(val,event) {
// 仅在有值输入的时候才弹出dropdown
if(this.multiple && this.filterable && val) {
!this.dropDownVisible && this.toggleDropDownVisible(true);
}
// 以下代码为el-cascader组件部分源码
if (event && event.isComposing) return;
if (val) {
this.filterHandler();
} else {
this.filtering = false;
}
}
}
Vue.component(Cascader.name, Cascader);
复制代码
问题4:el-cascader组件在多选模式下无法显示标签文字.
范围: Element-UI中Cascader组件
解决方案:将el-cascader下的el-tag样式由flex:1
改为:flex: 1 1 auto
;
问题5:flex布局下如果有position:absolute的元素,那么对这个绝对定位元素定位时,请不要依赖flex布局中的默认位置。
范围:全局
一个元素如果设置为position:absolute
之后没有设置具体的定位位置,那么就会使用在原文档流中应该处于的位置,但IE中如果在Flex布局里将flex子项设置为绝对定位后,样式并未保持在原本所处的位置。
例:
<div style="display:flex; align-items:center">
<i style="position:absolute">
</div>
<!-- 如果i元素是一个绝对定位元素,并且没有设置具体定位,那么我们期待的表现应该是i元素处于垂直居中的一个位置,在chrome中表现是这样的,但在ie中是不处于居中位置的,所以最好还是给一个具体定位 -->
复制代码
问题6:iview table组件开启拖拽排序功能在拖拽时会报错
原因:在IE中,拖放事件通过e.dataTransfer.setData存储数据时,设置的key只能是text或者url(大小写皆可),否则就会报错。而Table组件的拖拽通过e.dataTransfer.setData('index',index)保存索引导致报错
范围: IView库 Table组件
解决方案:在入口文件中引入iview组件库后手动修改组件中的方法,切记不要使用箭头函数,否则this指向错误。
import iView from 'iview';
iView.Table.components.tableBody.components.TableTr.methods.onDrag = function(e, index){
e.dataTransfer.setData('text',index);
};
iView.Table.components.tableBody.components.TableTr.methods.onDrop = function(e, index){
const dragIndex = e.dataTransfer.getData('text');
this.$parent.$parent.dragAndDrop(dragIndex,index);
e.preventDefault();
}
复制代码
问题7: IE浏览器会缓存网页中的发起的的ajax get请求的内容
原因:当请求方式是get方式时,IE浏览器会进行识别。如果该get请求的url是第一次请求的话,会请求服务器,从服务器中获取最新数据;如果该get请求的url不是第一次请求的话,那么该url就不会请求服务器,IE浏览器会直接从缓存中拿到上次该url获取的数据,从而会导致数据不同步
范围: 全局
解决方案(任选一种):
-
在get请求的url中增加随机标识,例如增加时间戳,一般是在
axios
的请求拦截器中进行操作,统一加上时间戳参数。 -
设置请求头'Cache-Control': 'no-cache'
// 此请求头告知浏览器使用本地缓存前需要跟服务器验证
const httpRequest = axios.create({
headers: {
'Cache-Control': 'no-cache'
}
})
复制代码
问题8:IE不支持粘性定位,即position: sticky
,请不要使用此种定位方式
问题9:NodeList在ie中不支持forEach方法
解决方案:NodeList本质为一个集合,是一个类数组结构,所以可以转为数组结构再使用相关数组api。
const body = document.body;
// ie下不支持此种方法
body.childNodes.forEach(node => {...})
// 转为数组结构后可安全使用
const nodeArr = [].slice.call(body.childNodes);
nodeArr.forEach(node => {...})
复制代码
问题10:后行断言正则表达式无法被识别
范围:全局
解决方案:
什么是后行断言,即 /(?<=a)b/
此种形式,此行正则的意思为 查找字符前紧跟a字符的b字符,由于ie无法支持此种正则,需要改造,可将其改造为普通捕获正则,如将上述正则改为/a(b)/
,同时取匹配结果中的第一个捕获组即可