creeperyang / blog

前端博客,关注基础知识和性能优化。
MIT License
2.63k stars 211 forks source link

这些年兼容的坑 #10

Open creeperyang opened 9 years ago

creeperyang commented 9 years ago

虽然早放弃IE6/7,然而兼容仍然是前端必须面对的事。

1. data uri兼容Edge

今天(2015/08/21)产品突然报了个bug:Microsoft Edge浏览器内,报表下载无法正常使用。

然而我并不是win10用户:joy: 花了一番力气,成功定位到错误:

edge bug

真是一头雾水,<a href='data:text/csv;charset=utf-8,xxxxxxx' download='y.csv'></a>chrome,firefox甚至ie9-11都能工作,怎么你号称更标准的Edge就这样子?

查阅文档,终于弄明白了这迷惑的警告信息:

  1. 当你点击<a>,我大Edge准备跳转到data:text/csv;charset=utf-8,xxxxxxx'
  2. 我认为data:text/是协议,然后这:shit:内容csv;charset=utf-8,xxxxxxx完全不认识啊!
  3. 你是不是给个doctype提示下?

Edge为什么没法智能识别data uri?

  1. <a>download属性并没有被Edge支持
  2. 微软以安全原因禁止用data uri来导航

怎么解决?

万幸的是Edge支持msSaveBlob,所以可以用它来代替data uri。

详细的可查阅http://stackoverflow.com/questions/14964035/how-to-export-javascript-array-info-to-csv-on-client-side

creeperyang commented 8 years ago

2. jQuery.fn.text()在IE8上的兼容性问题

背景:很简单的字符串模板,需要获取<script type='text/tpl'/>类似的文本内容。采用了$script.text()来获取,其中jQuery版本为1.8.3/1.11.3

在现代浏览器基本没问题,测试IE8时发现,取得内容为空字符串。

首先尝试$script.html()来代替,OK,可以取得文本。$.fn.html的实现采用elem.innerHTML,兼容性很好。

$script.text()为什么不兼容IE8?

https://github.com/jquery/jquery/blob/1.11.3/dist/jquery.js#L1536-L1565

以上是1.11.3版本的$.text的实现,可以看出:

  1. jQuery首先尝试用textContent去获取,很抱歉,IE8不支持;
  2. 然后尝试递归获取子节点的text。对<script>节点,发现IE8上其子节点为0(scriptDom.children--length: 0; scriptDom.firstChild: null)。

好了,这就是为什么$script.text()为空了:既不支持scriptDom.textContent,又任性地设定scriptDom.firstChild为空。 所以还是用$script.html()吧。

tiansh commented 6 years ago

Chrome 现在也禁止导航到 Data URI 了。 Firefox 目前不能从特权域继承权限地打开 Data URI 。

creeperyang commented 6 years ago

@tiansh 没有追踪这个了,你如果有空/有意愿,可以在这里补充新情况。

creeperyang commented 6 years ago

3. iOS 进行录音的兼容问题(getUserMediaAudioContext

需求是使用Audio API实现录音和上传服务器,在chrome上轻松实现了demo,但是在 iOS 11 上测试时,发现录音无效。

调试,发现 onaudioprocess 事件根本没用触发,why?

原因见 https://stackoverflow.com/questions/46363048/onaudioprocess-not-called-on-ios11/46534088#46534088

一步步调试发现:

  1. onaudioprocess 必须在 getUserMedia 后注册
  2. ScriptProcessor (由 createScriptProcessor 创建)也不能事先 connect ,要在getUserMedia 时connect。