`
white_crucifix
  • 浏览: 96751 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

与IE兼容性纠缠的这几个月(续)

阅读更多
    前段时间写了篇博客,简单描述了之前参与的系统中解决IE兼容性问题的一点过程。对于我个人而言,是非常厌恶微软IE789浏览器的,经常和同事开玩笑说,“IE789简直就是阻止人类进步的绊脚石”。我们这个系统从今年3月份正式上线,一直到现在,还在处于天天救火严重bug的状态,这其中包含了所有你能想出来的原因,当然之一就是IE兼容性问题。

    当然,不可否认,在解决IE兼容性问题的过程中,确实变相找到一些乐趣。至少比重复写着controller,service,dao,onclick,$().val()来的有意思。加上,这周中,用我上一篇文章中提到的一点,帮助了同事解决了迫在眉睫的问题,觉得还是有意义的。

    今天,要得瑟的内容,层面上,要比上一篇更高一个层次,就是性能问题。性能问题,可以说和ie无关,也可以说有关。比如你无端跑了极大量的循环,无论哪个浏览器里,都是不应该的。当然,在chrome里,可能是一瞬间,在ie里,却需要N秒。所以,又是和IE有关。

   
    以下是三个Case:

    1. 对HandsonTable单元格赋值

    handsonTable是一个国外的开源工具,用来提供仿excel的js表格控件,包括合并单元格等特性,是非常优秀的工具。

    我们的系统,打开某个页面的时候,非常慢,在chrome下也需要2秒+的样子,在IE9下需要10秒,IE8下需要14秒+,基本就是不可忍了。于是,我尝试着去解决这个性能问题。首先,当然是使用工具检测一下,在哪些代码上可能存在瓶颈。我选择的是chrome的profiles工具。有些人可能会觉得在chrome下测比较难,因为chrome跑js性能太好。但是,问题代码和正常代码的耗时比例,其实差别不会太大。我使用IE9的profiles测试过,心里是有底的。而且我在mac的虚拟机里跑一个ie9,加上win7在高分屏下的体验,总之就是不愿意。。

    通过profiles对js方法运行时间的统计,通过tree结构的结果列表分析,最终定位于handsontable的一个对单元格赋值的API。

    这里要插一句,定位到问题所在的过程,并非一帆风顺。不像自己写的代码,出了异常,能直接定位到某一行的某个变量。前端js里大多数都是第三方库,自己写的出问题的几率很少,很大程度上,是自己没用好第三方库的api,导致问题爆发在第三方库的逻辑中,而这些逻辑往往比较抽象。总之,依靠缩小范围,推理,猜测,动用一切经验和智慧,找出关键点。

   handsontable的这个api,setDataAtCell,很明显是给一个单元格赋值,再看我们使用的逻辑,是个使用了两层for循环给一个表格赋上初始值。当时就明白了,很明显,开发的过程中没想到实际使用时会出现上百列的场景,完全没想到这么多列下,一个一个赋值会慢的这么明显。

   解决的办法,我第一反应就是,批量赋值。尽管当时我完全不了解handsontable的api,但是我心里想,肯定有批量赋值的api,不然它就是shit!而且批量赋值的操作在底层一定不会像我们这样循环去做,不然还是shit!打开官网,粗粗扫了一遍api文档,操,没找到…… 然后开始细细地看,忽然发现setDataAtCell方法居然还可以传数组!由于官网文档写的实在太简陋,足足体会了好一会,才认定,一定就是它了。

   于是,我把双层for循环改成单层for循环。其实就是,一行一行赋值,而不是一个一个单元格赋值。耗时瞬减!IE下足足快了5秒。

   解决完这个问题,感觉还是很良好的,而且解决思路简单,没有副作用。但是下面这个case,就有点麻烦了。

   2. jQuery UI的sortable组件

    紧跟着上一个case,从原来10s+减少到5s+,已经提升了一倍性能,但是还不够,没有人愿意等5秒钟才打开页面。

    我本想说,用ie89的人活该,但是想想他们也是无辜的,因为有些老系统只支持老浏览器,总不能让用户一天到晚切换浏览器吧。这就是个恶心循环!

    接着说,依然使用profiles检测,可以看见前面setData部分的代码运行耗时比例已经降低很多,原来可是达到了70%+。此时另一个堆栈挑起了性能慢的大梁。通过tree结构分析,似乎涉及到jQuery UI的代码,但那时不了解代码逻辑,也就不知道为什么慢在jQuery UI上了。主要是我不知道 sortable和dragglable是属于 jQuery UI的,囧。。

    忽然想到,console.time()方法,可以测量代码执行时间,于是我在出问题的方法里,切了好几段,分别统计执行时间。运行,很明显,在创建sortable对像的方法上,消耗了大量的时间!问题点找到了,开始读逻辑,才发现原来给上文表格中的每一个单元格,都绑定了一个sortable组件。因为交互逻辑是,可以拖拽一些东西到表格内。

    google了一下,全世界都在抱怨sortable组件创建时的消耗大。当时一想,坏了,要是设计就必须放这个组件,就不能随意砍掉,而且几乎没有优化余地啊。

    此时,走了一个弯路,由于是失败的弯路,准备放在最后讲。

    读通原有设计思路是不可避免得了,耐下心读吧。同时还去官网学习了我不熟悉的sortable,dragglable,droppable组件的使用。然后,惊!天!大!发!现!

    先科普一下,sortable的作用是,某个区域内的元素,可拖动交换位置,比如一个列表中的每一行。draggable定义了可拖动元素,而droppable是指该区域可被放置拖动的元素。因此sortable就好比,draggable和droppable的结合。
   

    页面逻辑是,用户从其他地方拖动一个元素到表格的一个单元格内,再拖动一个新元素进来时,会覆盖。然后顿时震惊了,现在将单元格本身作为一个sortable区域,而内部却永远只需要存在一个元素,就完全没有必要成为sortable区域啊,又不需要排序!于是将sortable组件改为droppable组件的想法自然产生。

    由于我也不知道droppable的性能会被sortable好多少,所以怀着惴惴不安的心情做了尝试,中间省略很长时间调节代码逻辑的过程,这也不是容易的过程。。。

    确实快了很多!之前IE9下降到5秒+的过程,如今只需要2秒了!换句话说,两个优化以后,ie9从10秒降到2秒,同时,ie8也从14秒降到4秒。

    至此,这部分就不准备再调节了,虽然理论上还存在优化的余地。

   3. jquery选择器 :not

    这个Case准备简单掠过,因为直接砍掉了一部分逻辑,不算真正改好,(其实我觉得原逻辑也不好,所以砍掉就砍掉了。。。。嘿嘿偷偷的)

   通过profiles和 console.time 定位到了一个jquery选择器居然执行了好几秒,这里含有多个选择器的并列,还涉及到not语法,通过调试,发现单个使用not时没有性能问题,但与其他并列选择器的同时使用,就出奇的慢。关于这个我就没有深究,心想这not这种东西就和sql里not,like之流有异曲同工之妙,总有慢的理由。。。。遂,砍之。。

  
   到这里,经历过的三次调优就结束了,之后由于参与其他任务,没时间调优,所以就放置一边了。总之,和前一篇博客一样,记一件有意义的事情。


——————————————————————————————————

前面讲过一个弯路,虽是弯路,但是挺有意思的尝试。

由于sortable慢,一开始又不知道可以怎么优化。于是想着能不能将这种卡顿感弱化。js是一个单线程的语言,放在浏览器里就是,如果一直在忙于执行一段任务,其他事情就会被卡住,包括用户页面操作,页面无响应,弹出IE是否结束脚本警告框,等等。

那么如果我自己模拟一个时分复用,将5秒钟的任务分割成N分,每5/N秒中断一次,因为有了中断,js线程就不会永远卡在当前任务上,有机会让其他任务插一脚执行,比如页面点个按钮啥的。在stackoverflow上拷了段js代码,用promise辅以setTimeout,模拟出一个时分复用的样子。

当然结果还是不理想啦,感觉卡顿感更严重了啊,页面点击时好时坏的,想着不能从根本上解决,还是不行啊,于是只能开始啃上下文代码。。。
——————————————————————————————————
2
1
分享到:
评论
5 楼 weskul 2015-09-15  
white_crucifix 写道
weskul 写道
新手,看源码for循环去掉一层完全不知道咋下手,改这个代码好难!


哦哦,handsontable是吧,不知道我们问题是不是一样

原来双层for循环的做法是,使用setDataAtCell这个方法,一个一个单元格去赋值。 数量多的时候很慢。

单层for循环的做法是,还是使用setDataAtCell,但是是一行一行赋值,即传入的参数为数组。测试下来快很多。

仔细看setDataAtCell这个方法的官网API就能发现,它是能传递数组,(说不定还能传递二维数组,即整个表格,猜的)

我去试试
4 楼 white_crucifix 2015-09-15  
weskul 写道
新手,看源码for循环去掉一层完全不知道咋下手,改这个代码好难!


哦哦,handsontable是吧,不知道我们问题是不是一样

原来双层for循环的做法是,使用setDataAtCell这个方法,一个一个单元格去赋值。 数量多的时候很慢。

单层for循环的做法是,还是使用setDataAtCell,但是是一行一行赋值,即传入的参数为数组。测试下来快很多。

仔细看setDataAtCell这个方法的官网API就能发现,它是能传递数组,(说不定还能传递二维数组,即整个表格,猜的)
3 楼 white_crucifix 2015-09-15  
weskul 写道
新手,看源码for循环去掉一层完全不知道咋下手,改这个代码好难!


你要改哪个?
2 楼 weskul 2015-09-12  
新手,看源码for循环去掉一层完全不知道咋下手,改这个代码好难!
1 楼 weskul 2015-09-12  
博主,能发个修改的代码吗!谢谢!!!

相关推荐

    IE兼容性解决IE兼容性解决IE兼容性解决IE兼容性解决

    在互联网的发展历程中,Internet Explorer(IE)曾是全球最广泛使用的浏览器,但由于其独特的解析方式和不一致的实现标准,IE的兼容性问题一直是开发者头疼的问题。本文将深入探讨如何解决IE兼容性问题,尤其是针对...

    判断IE8兼容性视图工作模式

    标准模式按照最新的Web标准来渲染页面,而兼容性视图则是为了与旧版的网页兼容,模拟旧版IE(如IE7或更低版本)的行为。用户可以通过工具栏上的按钮或者设置来切换这两种模式。 要检测IE8是否处于兼容性视图,我们...

    如何解决IE兼容性问题

    由于IE浏览器的版本差异导致了许多兼容性问题,这使得开发者不得不采取一系列策略来适应这些差异。本文将详细介绍如何解决IE兼容性问题,并提供一些实用的方法。 #### 一、理解IE兼容性问题 IE浏览器在不同时期...

    IE兼容性测试工具

    这款工具极大地简化了开发者对IE浏览器兼容性的验证工作,提高了工作效率。 **核心功能** 1. **多版本模拟**:IETester能同时打开多个独立的IE实例,每个实例对应一个特定的IE版本,这样开发者可以在同一界面上...

    VC++ IE兼容性视图网站 IECompatibleViewsDemo.zip

    通过代码添加、删除、查询等操作IE兼容性视图网站。封装类,直接调用就可以了。通过代码添加、删除、查询等操作IE兼容性视图网站。封装类,直接调用就可以了。通过代码添加、删除、查询等操作IE兼容性视图网站。封装...

    IE10兼容性白皮书

    总体而言,IE10兼容性白皮书是一份全面的指南,不仅涉及了IE10与HTML5的兼容性问题,还包括了网站优化、用户体验提升等方面的先进技术和方法。通过遵循这些指南,开发者可以为用户打造更加流畅、便捷和创新的网页...

    IE兼容性插件

    "IE兼容性插件"正是为了解决这一问题而存在的工具,它能够帮助提升网站在IE浏览器上的表现,使其更加符合现代Web标准。 PIE,全称为“ Positioned Absolutely, Everything Else”, 是一种专门针对IE浏览器的CSS3...

    ASP.NET与IE11兼容性解决方法

    然而,ASP.NET与IE11之间可能存在兼容性问题,特别是涉及到JavaScript功能时,如在描述中提到的“__doPostBack”未定义错误。 “__doPostBack”是ASP.NET中的一个关键JavaScript函数,主要用于处理页面回传事件。当...

    ie设置兼容脚本

    一个windows下用来设置ie兼容的脚本,方便批量设置,不用每台机器都设置一遍了; 一个windows下用来设置ie兼容的脚本,方便批量设置,不用每台机器都设置一遍了

    IE6-IE11兼容性问题列表及解决办法.rar

    对于IE6到IE11这一系列的Internet Explorer浏览器,由于它们之间的差异以及与其他现代浏览器的不同,开发者经常遇到各种兼容性问题。本文件“IE6-IE11兼容性问题列表及解决办法.rar”正是针对这些难题提供解决方案的...

    如何解决ie兼容性问题

    在网页开发过程中,IE(Internet Explorer)浏览器的兼容性问题一直是一个挑战,尤其是在多个版本共存时。为确保网站在不同浏览器上呈现一致的效果,开发者需要采取一系列策略来解决这些问题。以下是一些解决IE兼容...

    FF和IE兼容性问题

    总的来说,理解和处理FF与IE之间的CSS兼容性问题需要开发者具备深入的CSS知识,并且时刻关注最新的浏览器发展趋势。随着IE的逐渐淘汰,更多的注意力转向了对Edge浏览器和其他现代浏览器的兼容性优化。然而,对于仍需...

    IE7.JS解决IE兼容性问题方法

    总结来说,"IE7.JS解决IE兼容性问题方法" 这个主题涵盖了解决旧版IE浏览器兼容性问题的技术和策略,通过使用类似IE7.JS这样的库,开发者可以减少在不同版本IE间适配的工作量,提高网站的用户体验。

    IE5,IE6,IE7,IE8的css兼容性列表

    在互联网发展的早期,微软的Internet Explorer(IE)浏览器曾经占据主导地位,尤其是IE5、IE6、IE7和IE8这几个版本。每个版本都有其独特的特性和对CSS(层叠样式表)的支持程度,这对于前端开发者来说是必须要了解的...

    百度编辑器1.4.3.3版本IE8兼容性问题

    压缩包中的“百度编辑器1.4.3.3版本IE8兼容性问题”很可能包含了一个修复此问题的特定JS文件,该文件可能包含了针对IE8的兼容性补丁。在实际应用中,只需将这个文件引入到项目中,即可解决ueditor在IE8下的错误。 ...

    解决各种IE兼容问题_IE6_IE7_IE8_IE9_IE10

    对于使用Microsoft IIS服务器的情况,可以在web.config文件中配置一个自定义头部,比如设置为`IE7 mode`,这样所有请求的页面都会按照IE7的兼容性标准来处理。 另一种解决IE兼容性问题的方法是使用JavaScript库,如...

    IE7与IE8的兼容性 配置文档

    为了解决IE7与IE8之间的兼容性问题,Microsoft引入了一个名为`X-UA-Compatible`的HTTP头字段,允许开发者指定IE应该使用哪种渲染模式来显示页面。这一字段可以通过服务器端设置,也可以通过HTML元数据插入到页面中。...

Global site tag (gtag.js) - Google Analytics