技能get√
先说一个需求,我想给一个元素应用另外一个指定元素的样式,应该怎么做?对于一个特定的项目,我想通常做法是规范代码风格,直接把class复制过来就可以了。但现实情况可能并不会如此简单。比如我们假定这个指定元素是不可预测的,它的样式可能由class控制,也可能由更复杂的选择器控制,甚至可能写在style属性里。这该怎么办呢?
过程就懒得说了,直接说结论吧。上代码:
if(!window.getComputedStyle){
window.getComputedStyle=function(node){
return node.currentStyle;
}
}
var a=document.getElementById("A");// source node
var b=document.getElementById("B");// target node
$(b).css(window.getComputedStyle(a));
代码很短,先看最后一句,我们用window.getComputedStyle()
方法来获取一个节点的最终样式。OK,也许你没有用过这个方法,但作为一个FE,你一定见过下面这个画面:
图1: Computed Style 截图
这是在chrome的开发者工具中,通过element选项卡可以查看dom节点样式的截图,红框中的就是这个节点最终样式的计算结果。而window.getComputedStyle()
就是BOM提供给大家得到这样一个计算结果的接口。那么剩下的就好理解的,通过window.getComputedStyle()
方法拿到指定元素的最终样式集,这个结果呢又正好是一个$.css()
方法能接受的对象(这个对象下面会讲)。于是上述代码中,我们通过$.css()
方法直接将样式覆盖给了目标元素。当然,如果不想用jquery,我们也可以通过遍历这个对象,并操作目标元素的style属性达到目的,代码就不贴了。
window.getComputedStyle()
知道了这种做法,我们再来好好研究一下window.getComputedStyle()
这个方法。
The
Window.getComputedStyle()
method gives the values of all the CSS properties of an element after applying the active stylesheets and resolving any basic computation those values may contain.
window.getComputedStyle(element [, pseudoElt])
最多接受两个参数,第一个参数element
是我们想要获取样式的dom节点,这个参数是必须的,仅有这一个参数呢是这个方法的基本用法。但css3中添加了伪元素的支持,第二个参数正是用来指定伪元素的。我们可以传递像”:before”、”:after”之类的值。
有些技术文章把第二个参数解读成伪类,经我验证,这是不对的,伪类的样式是无法通过这种方式获取的。
至于这种做法的兼容性,相信你也能猜到:IE6-8是不支持的。对伪元素的支持情况会更糟一些。
表1:浏览器对window.getComputedStyle()
的支持情况
特性 | Chrome | FireFox | IE | Opera | Safari |
---|---|---|---|---|---|
基本支持 | 支持 | 支持 | >=9 | 支持 | 支持 |
伪元素支持 | 支持 | 支持 | >=11 | 不支持 | 支持 |
又是苦逼的IE。不过这次问题不算大。不知道你还记不记得代码最上面几行?回过头去看一眼:对于IE,我们用了element.currentStyle
属性,同样可以满足我们的需求。所以如果不涉及伪元素,配合示例代码里的shim,我们应该可以没有顾虑地使用window.getComputedStyle()
。
很多地方(例如以前的Jquery)在使用window.getComputedStyle()
时并没有直接在window
上调用,而是使用的window.defaultView.getComputedStyle()
。事实上现在我们可以认识window.defaultView
就是window
。Jquery也将这部分代码修改了,见jquery #10373。可能会在IE的弹出窗口和低版本Firefox的frames中使用会有一些异常。Jquery认为在IE弹出窗口中使用必须加defaultView
,而Firefox的情况则不可以加defailtView
,于是做了一个shim,可以排除两种异常。可以参考下:
define(function() { return function( elem ) { // Support: IE less than 11+, Firefox less than 30+ (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" if ( elem.ownerDocument.defaultView.opener ) { return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); } return window.getComputedStyle( elem, null ); }; });
更详细的内容有兴趣的朋友可以参考:
CSSStyleDeclaration
再来说说window.getComputedStyle()
的返回值。window.getComputedStyle()
会返回一个CSSStyleDeclaration
对象。这个对象是只读的,意味着我们只能取其值,不能为其赋值。所以上面的示例代码中我们采用$.css()
方法来设置css样式。这个对象应该如何用,这篇文章里面我不想赘述,有兴趣的可以参考MDN的文档。想直观了解这个对象长什么样子的同学请点击F12键,我在浏览器的console里输出了一个CSSStyleDeclaration
对象。
最后提醒下不同浏览器下,css的属性名可能有差异,如比较突出的cssFloat/styleFloat/float,jquery可以屏蔽掉浏览器这方面的差异,推荐之。