最近遇到了两个IE下的兼容问题(产品目前还需要兼容IE8,所以没办法,运行效果虽然不好,但是也仍然兼容着吧)
问题描述:
1, 在更改IE窗口的时候,反应非常慢,甚至卡死
2, 在chrome运行正常,但是在IE8下样式大片失效
分析原因:
问题1: 通过查找, 发现是IE下对 window 的 resize 事件的判断并不是以windows 为准, 而是任何 dom 元素的更改都会触发此事件.
由于项目是基于 reactjs 的组件, 并且会监听 resize 事件从而做出自适应调整. 此调整又会导致 IE 下的 resize 事件, 从而, 死循环 诞生.
问题2: 感觉不是兼容问题导致的, 因为很多的样式失效. 组内一哥们经过"深入"钻研, 发现更改总 less 文件的 import 会部分解决此问题,
但仍然会导致其他模块的样式更改. 我一起参与分析后, 发现样式在IE下就像丢失一样, 不仅仅是兼容问题. 经过查找, 发现在IE9下的css rule
有长度限制(单个文件, 即单个CSS 文件限制rule数量为 4096. 此处做一个自己的说明, 此处的 rule , 即为一条 css 规则, 如果有逗号的多个
写在一行的规则, 是会计算为多个规则的~~~~) 所以单纯的抽离出来CSS样式, 写为一行是不可以的. 虽然代码量减少, 但是rule 数量并没有
减少多少. 需要对样式进行公共性归纳, 处理, 调整CSS的规则.
问题解决:
1: 通过在 resize 事件的时候 增加判断窗口大小是否更改进行解决
示例方法如下:
//so的搬运工 ^_^ var winWidth = $(window).width(), winHeight = $(window).height(); $(window).resize(function(){ var onResize = function(){ //The method which alter some css properties triggers //window.resize again and it ends in an infinite loop someMethod(); } //New height and width var winNewWidth = $(window).width(), winNewHeight = $(window).height(); // compare the new height and width with old one if(winWidth!=winNewWidth || winHeight!=winNewHeight){ window.clearTimeout(resizeTimeout); resizeTimeout = window.setTimeout(onResize, 10); } //Update the width and height winWidth = winNewWidth; winHeight = winNewHeight; });
2: 通过精简css rule进行处理. 判断有多少rule的js(在非IE下运行~~)
function countCSSRules() { var results = '', log = ''; if (!document.styleSheets) { return; } for (var i = 0; i < document.styleSheets.length; i++) { countSheet(document.styleSheets[i]); } function countSheet(sheet) { if (sheet && sheet.cssRules) { var count = countSelectors(sheet); log += ' File: ' + (sheet.href ? sheet.href : 'inline <style> tag'); log += ' Rules: ' + sheet.cssRules.length; log += ' Selectors: ' + count; log += ' --------------------------'; if (count >= 4096) { results += ' ******************************** WARNING: There are ' + count + ' CSS rules in the stylesheet ' + sheet.href + ' - IE will ignore the last ' + (count - 4096) + ' rules! '; } } } function countSelectors(group) { var count = 0 for (var j = 0, l = group.cssRules.length; j < l; j++) { var rule = group.cssRules[j]; if (rule instanceof CSSImportRule) { countSheet(rule.styleSheet); } if (rule instanceof CSSMediaRule) { count += countSelectors(rule); } if( !rule.selectorText ) { continue; } count += rule.selectorText.split(',').length; } return count; } console.log(log); console.log(results); }; countCSSRules();
OK, 完毕. 附上自己参考的地址. 对于前端来说 stackoverflow 的确是好地方, 要经常去查找看看. 这是一个认真做事的地方.
http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer
http://stackoverflow.com/questions/9906794/internet-explorers-css-rules-limits