记一次,vue 项目调整兼容 IE8+
要点
- flex 样式兼容
- element UI 部分组件兼容
详细
交代说明
公司项目开发接近收尾,突然硬性要求兼容 ie9。项目搭建时,采用 vue2.6 + elementUI + axios,使用大量 es6 语法(Promise),和 flex 布局。
需要面临的问题
- elementUI 针对 IE 部分存在兼容问题
- axios 针对 IE 下返回表现不同
- flex 只支持到 IE10
- Promise IE 系(不含除去 Edge) 不支持
基本兼容垫片
1 | npm install --save-dev babel-polyfill |
在 webpack config.js 中加入:
1 | module.exports = { |
IE 11 中接口返回值接收失败
查找发现 Axios 返回值 response 的 data 是个字符串的 json。需要转换为 JavaScript 对象,才可正常读取。
代码如下:
1 | import axios from 'axios' |
关于 looseJsonParse 转换为 JavaScript 对象
其实也可使用 JSON.parse() 【 ie8+ 】
虽然可以 eval(’(’ + obj + ‘)’),但不建议使用
由于性能和容易被劫持攻击等原因,推荐使用 looseJsonParse 方式 戳这里
插曲:eval 与 JSON.parse()
详细了解?戳这里
JSON.parse 只是格式化 json;要求严格的 json 格式(只能解析属性名是双引号包裹的字符串对象【key、value 都要双引号】,并会忽略换行和空格(值外面))。
eval 函数可将一个 JavaScript 代码字符串求值成特定的对象,解析 json 只是其中一点功能。
- eval 解析 json 需要加入’()’ eg: eval(’(’ + obj + ‘)’)
- eval 对 josn 的格式没有特殊要求,但是会直接执行里面内容进行运算。(eval 相当于一个执行环境)eg: eval(’(’ + ‘{data:new Date()}’ + ‘)’)
eval 解析 json 需要加入’( )’ 是因为
eval()相当于一个执行环境,当你不加括号的时候,jsonstr1 会被认为是一条复合语句。运行的时候就会逐个字符的解析。
但是加上括号的时候,jsonstr1 就当做一个表达式去运算。从括号开始就被当做了对象进行识别。
IE 9 中接口返回值的 data 为 undefined
查找发现
在 Axios config 中,默认设置了 responseType: ‘json’ 。 ie9 下不支持,返回数据没有 data 字段
解决
注释 // responseType: ‘json’ 就好
IE 中 elementUI 组件 bug
NavMenu 导航 组件 移入下拉报错(TypeError 对象不支持此操作)
查找发现
NavMenu 组件默认使用的 hover 方式不被 IE 支持
解决
在对应的 el-menu 加入属性 menu-trigger=“click” mode=“horizontal”
注意:
文档说的很明确,menu-trigger (只在 mode 为 horizontal 时有效)
IE 下 table 组件 下表格与表头错位的兼容问题
问题
因为表格宽度未设置 100%,导致计算每列出现几 px 的精度差,最后导致整体样式错乱
解决
全局接入 css 补丁:
1 | body .el-table th.gutter { |
IE 下报错 :Unhandled promise rejection SyntaxError: 缺少 ‘;’ 或 Unhandled promise rejection SyntaxError: 缺少 ‘)’
查找发现
vue-chart 出现了兼容问题。
解决
步骤 1: npm i echarts vue-echarts -S
步骤 2:npm i resize-detector -S
步骤 3:
当使用 Vue CLI 3+ 时,需要在 vue.config.js 中的 transpileDependencies 增加 vue-echarts 及 resize-detector,如下:1
2
3
4
5
6
7// vue.config.js
module.exports = {
transpileDependencies: [
'vue-echarts',
'resize-detector'
]
}当使用 Vue CLI 2 的 webpack 模板时,需要按下述的方式修改 build/webpack.base.conf.js:
1
2
3
4
5
6
7
8
9
10
11{
test: /\.js$/,
loader: 'babel-loader',
- include: [resolve('src'), resolve('test')]
+ include: [
+ resolve('src'),
+ resolve('test'),
+ resolve('node_modules/vue-echarts'),
+ resolve('node_modules/resize-detector')
+ ]
}
- 还有一种方案,直接使用 echarts
兼容样式问题
问题
最早使用了大量的 flex 布局,导致 IE9 无法正常显示。
解决
在 index.html 中借助 “<!–[if IE 9]>” 来引入针对 IE9 的样式补丁,如下:
1 | <!--[if IE 9]> |
IE9、10、11、edge 下 头像裁剪上传 报错(提示对象或方法未定义)
由于此处代码是同事写的,屡了下流程:
- 通过 点击 label 标签 触发 隐藏 input file 控件,选取图片;
- 通过 FileReader 读取文件 使用 FileReader.readAsArrayBuffer() 得到 blob 对象;
- 使用 window.URL.createObjectURL 得到 dataUrl 喂给 vue-cropper 组件进行图片裁剪;
- 从 vue-cropper 裁剪后,返回得到 base64,通过 new File() 转换为 file 文件; // 或者 blob 对象
- 使用 formData 发送给后台;
- 后台返回成功后,修改页面头像,流程完毕。
了解到都使用哪些东西,还需要了解下基本知识。
MDN 下了 File、 blob、URL.createObjectURL
技术实现采用了一些比较高级的 api ,对于 IE 来讲不是太友好,总结如下:
浏览器 | File | blob | createObjectURL | new File(转换为 File 文件) |
---|---|---|---|---|
IE9 | NO | NO | NO | NO |
IE10 | YES | YES | YES | NO |
IE11 | YES | YES | YES | NO |
Edge | YES | YES | YES | NO |
看起来情况不太乐观。那么,一个一个解决。
IE9 下头像上传
从上面看来,IE9 不支持高级 api ,原来的整套应该全部不适用。
果然,从 第一步 获取文件就在报错。 input file 控件 的 target.files 是 udefined。难道无法拿到文件?
补习了下:
得到如下信息:
低版本 IE 由于 JS 安全问题,不允许 JS 访问本地文件,所以无法获取 files
对于低版本的 IE 可以使用 ActiveXObject 获取文件对象, 但是默认情况下
ActiveXObject 为不可用的, 所以要想使用此对象要先启用设置, 即:
Tools(工具) / Internet options(选项) / Security(安全) / Custom level(自定义级别)
找到"Initialize and script ActiveX controls not marked as safe for scripting"
设置为"Enable(not secure)"即可.
获取文件路径
出于安全性的考虑,低版本 IE 上传文件时屏蔽了真实的本地文件路径,
以 C:\fakepath**取而代之, 所以默认情况下通过 fileEle.value 不能获取到
文件的真实路径.
如果想获取真实路径, 有两种方式:
- 通过设置 IE 的安全设置, 即:
Tools(工具) / Internet options(选项) / Security(安全) / Custom level(自定义级别)
找到"Include local directory path when uploading files to a server"
设置为的"Enable"- 使用 JS 获取, 即:
fileEle.select().blur();
var filePath = document.selection.createRange().text;
然后试了下 在 IE 下使用 ActiveXObject 读取文件。然后读取文件还要设置【⊙﹏⊙b 汗】,放弃。
与产品沟通了下。本着华丽升级,优雅降级的原则【好吧,就是我也没有办法】。IE9 下可以取消裁剪。
先科普下