最近由于公司项目的需要,一直在研究IE8下angularjs控件兼容性的问题,其中最棘手的就是ui-grid的兼容性问题,虽然在github上ui-grid的官方主页上明确表示,ui-grid支持IE8,但现实并不尽人如意,如果您也还在苦恼ui-grid在ie8下兼容性的问题或者正在寻找IE8下适合的angularjs grid,这篇文章可能会帮助到您。
废话不多说,解决ui-grid ie8兼容性问题可以归纳为两个步骤:
1.让angularJS 在IE8下跑起来(前提条件)
2.让ui-grid在IE8下跑来
解决了步骤1,才能解决步骤2。解决步骤1,可以参照我的另一篇文章:angularJS与IE8整合
下面我们着重介绍ui-grid在IE8下的解决方案 (如下的代码都来自于ui-grid.js源码,需要修改控件代码)
1.解决Object.defineProperty
在ie8下启动angularjs成功后,发现Grid已经挂了,分析原因发现Object.defineProperty出现了问题,原因在于在IE8下只支持对DOM元素定义property,无法对对象定义property
修改为:
分析原因:
我们从MDN的官网搜索发现,显然IE8有着一套特殊的object.defineProperty标准,即只能在DOM元素上定义属性,如果想要在非DOM元素上定义属性,要给定义属性一个初始值value而且writable,configurable,enumerable三个属性值都为true。
注:这种定义非DOM属性的方式只适用于IE8,W3C标准规定value与访问器(get(),set()方法)不能同时存在,有趣的是,IE8以上的版本采用了这一标准,也就是说这种写法只能存在于IE8,在实际操作的时候我们可以根据浏览器类型,加载相应的JS
2.解决getComputedStyle
ie8不支持getComputedStyle,具体表现如图所示:
第一种解决方案: 将getComputedStyle换成ie8支持的currentStyle
好处:简单直接,能够解决问题
坏处:不兼容IE8以上的浏览器
第二种方案:改变写法,同时加入polyfill(补丁)
改变写法如下:
在index.html的header中加入getComputedStyle的polyfill
注:getComputedStyle的polyfill网址为https://github.com/jonathantneal/polyfill
包括了很多ie8不支持方法属性的polyfill,可以根据需要选择使用。
3.解决getElementsByClassName
ie8不支持getElementsByClassName,具体表现如图所示:
很不幸,经过多方搜索在网上并没有找到对应的polyfill,但我们可以自己写他的补丁,如下:
然后将ui-grid中所有用到getElementsByClassName的地方改成如下的形式:
改动前:
var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
改动后:
var footerViewport = getElementsByClassName($elm[0],'ui-grid-footer-viewport')[0];
ui-grid的CSS实现机制为,在模板中定义style标签,然后动态计算css,之后再用指定把CSS注入到对应的style模板中,对应如图所示:
对应指令如下:箭头为出错位置:
原因为:ie8并不支持text()方法且也不支持引用特殊标签<style>,这就导致了如图所示的结果 :样式全部乱了,style中没有内容。
解决方案:放弃使用angularjs本身的指令注入,使用动态生成style标签的形式。
5.解决event.preventDefault()与event.stopPropagation()
由于ie8均不支持event.preventDefault()与event.stopPropagation();所以改用ie8的event.returnValue=false;这一方法,适用于大多数情况。
event.preventDefault()改为:
(event.preventDefault) ? event.preventDefault() : event.returnValue = false;
event.stopPropagation()改为:
(event.stopPropagation) ? event.stopPropagation() : event.returnValue = false;
至此:ui-grid兼容性问题全部解决,解决后的样式如图所示: