97

【原创】抓个Firefox的小辫子,围观群众有:Chrome、Edge、IE8-11 - 三生石上(FineUI...

 6 years ago
source link: http://www.cnblogs.com/sanshi/p/7920103.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【原创】抓个Firefox的小辫子,围观群众有:Chrome、Edge、IE8-11

很多人都知道我们在做FineUI控件库,在这 9 年多的时间里,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅:

这类BUG之所以被大家所深恶痛绝,在于其隐蔽性,很多时候不能用常规的逻辑去分析。另一个原因的开发人员一般都很善良,出现问题总是从自身找原因,很少会怀疑到IDE,浏览器这些开发工具上面来。

事实情况是,浏览器也是开发人员开发的,是个软件就有BUG!

今天公开的这个Firefox BUG一直长期存在,最新的 Firefox Quantum 也位列其中,下面就听我详细道来......

昨天一个客户向我们反馈了一个问题,页面初始时表格未显示,等页面回发后表格才显示出现。奇怪的是,这个问题仅在Firefox下出现,Chrome、IE下是正常的。

下面是和客户沟通的截图:

48817-20171129135451050-788399202.png
48817-20171129135458144-1230917815.png

接到反馈后,我们立即进行了测试,在Chrome,Edge,IE下页面第一次打开是这样的:

 

48817-20171129141130378-1881033924.png

但是在Firefox中,页面第一次打开时流程信息分组面板(GroupPanel)中的表格不见了:

48817-20171129151238159-475669661.gif

 

只有在页面回发后,才会显示出来。初步调试可以看出,Firefox下页面第一次加载时表格外部容器的高度不对:

48817-20171129141050331-2030023735.png

由于这个问题只在Firefox下出现,其他浏览器Chrome、Edge、IE8-11均显示正常,因此我们初步判断是Firefox的BUG导致FineUI布局时计算外部容器错误。

为了排除这是Firefox 57.0 新版引入的问题,我们还特意下载了一个老版本:

48817-20171129145038300-1722890105.png 

结果发现,Firefox老版本存在相同的问题,看来这个问题一直存在。

经过一段紧张的排查,我们终于通过一个简单的HTML页面重现了这个问题:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<style>
*, :after, :before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
</style>
</head>
<body>
<fieldset id="fieldset1" style="border:solid 1px red;width:500px;position:absolute;top:0;left:0;">
<legend>fieldset</legend>
</fieldset>
<script>
$(function () {
$('#fieldset1').height(200);
alert(parseInt($('#fieldset1').height(), 10));
});
</script>
</body>
</html>  

Firefox下测试:

48817-20171129143303065-1966365316.png

 

Chrome下测试:

48817-20171129143314737-1403496393.png

 

Edge下测试:

48817-20171129144709690-1329777298.png

 

IE11-IE8下测试:

48817-20171129144718472-303383689.png

 

经过对代码的进一步测试发现,这个BUG在Firefox下出现需要满足如下三个条件:

  1. 设置CSS全局属性:box-sizing: border-box
  2. HTML标签为:fieldset
  3. fieldset绝对定位:position:absolute

当同时满足这三个条件时,通过JS对 fieldset 标签设置高度后,立即获取高度无效!!!

这个简单的示例中,如果把:

<fieldset id="fieldset1" style="border:solid 1px red;width:500px;position:absolute;top:0;left:0;">
<legend>fieldset</legend>
</fieldset>  
<div id="fieldset1" style="border:solid 1px red;width:500px;position:absolute;top:0;left:0;">
</div>  

则Firefox下就不会有问题:

48817-20171129143151800-859303034.png

而我们的 FineUI 的 GroupPanel 控件正是满足了这三个条件,才巧遇了这个Firefox一直存在的BUG:

48817-20171129143213784-1764675460.png

在FineUI 布局中,由于当前页面是占据整个屏幕的,所以宽度和高度是从外而内设置的。上面图片中经历了这么一个推理过程:

  1. 根据页面的高度设置最外层节点的高度
  2. 一层一层向内推进,可计算出fieldset的高度为135px
  3. 通过JS设置fieldset高度等于135px
  4. 此时获取fieldset的高度却不是135px,导致设置表格的外部容器的高度出现偏差(9.5px)

当然最好的解决办法就是等Firefox更新了,什么时候修正这个BUG。但是你能指望Firefox什么时候修正这个问题呢?既然已经存在几年的时间了,很有可能继续存在下去。

从另一个角度讲,用老版本Firefox的用户怎么办?问题还是要解决,不能改变别人,只要拿自己动手了。

在经历了那么多浏览器BUG之后,我们已经很淡定了,不就是设置节点属性后不更新么,我们来强制更新一把!

下面的方案可以很好的解决这个问题,并且仅对Firefox进行处理:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<style>
*, :after, :before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
</style>
</head>
<body>
<fieldset id="fieldset1" style="border:solid 1px red;width:500px;position:absolute;top:0;left:0;">
<legend>fieldset</legend>
</fieldset>
<script>
$(function () {
$('#fieldset1').height(200);
if (/firefox/i.test(window.navigator.userAgent)) {
// 强制浏览器重新绘制fieldset节点
var fieldsetNode = $('#fieldset1');
fieldsetNode.css('overflow', 'auto');
fieldsetNode[0].scrollWidth;
fieldsetNode.css('overflow', 'hidden');
}
alert(parseInt($('#fieldset1').height(), 10));
});
</script>
</body>
</html>

最终效果图

48817-20171129150819190-1222392719.gif

喜欢三石的文章,你就给个推荐呗!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK