十一月
29

【JavaScript温故知新】几种设置节点CSS样式的方法

头题】这又是一篇探讨文。即为我学习中总结,不是教程,不是技术样板,请你抱着怀疑的、挑错的态度来阅读此文。

JavaScript和DOM结合的如此之紧,几乎很大一部分代码都是在操作结点。其中就会涉及到设置修改节点的样式。

驼峰写法与浏览器兼容性

所谓“驼峰写法”即是指由有语意的单词组成的键值从第二个单词起要首字母大写,如背景颜色“background-color”使用JS就需要写成“backgroundColor”。类似的还有marginLeft、fontSize、backgroundPosition、overflowX等等。。。

但是也有一些容易犯的陷阱,如可不要把background写成backGround、overflow写成overFlow。。。。

还有浏览器的兼容性问题,有两点要注意,一个是透明opacity,IE下不直接支持透明,但支持滤镜透明,即要写成“alpha(opacity=value)”;另一个是浮动float(float是保留字),IE下是styleFloat,火狐、chrome等标准浏览器下是cssFloat。opera貌似是两者都支持。

最基本的写法

node.style.style-key=value

这种做法来说,没有什么不妥,缺点在大多数人看来也就是需要重复写太多代码。比如将node节点样式设置为“高度200像素,宽度300像素,右浮动,背景颜色为红色”,就需要写以下大堆的代码:

node.style.height="200px";
node.style.width="300px";
node.style.cssFloat="right";//标准浏览器
node.style.styleFloat="right";//IE
node.style.backgroundColor="red";

有人就会觉得前面一大堆“node.style.”重复性的代码完全可以通过函数封装来省略书写。其实还可以这样来写

var sty=node.style;
sty.height="200px";
sty.width="300px";
sty.cssFloat="right";//标准浏览器
sty.styleFloat="right";//IE
sty.backgroundColor="red";

这样就少了很多的代码。

不过通过函数封装可以将写法更加简单化。所以就有了下面的方法

函数封装后的方法

/*!
 @FileOverview 设置节点样式
 @Author liuqiqi || imqiqiboy@g mail.com || http://www.qiqiboy.com
 @date 2010/11/29
 @param node 节点对象
 @param css 设置的样式,对象写法,同时兼容短横线相隔与驼峰写法,eg: {'height':'200px',width:'300px',margin-left:'20px',marginTop:'10px'}
 @return none
*/
function setNodeStyle(node,css){
    for(var _atr in css){ //枚举每个值
        var arr = _atr.split('-'), //分割成数组
            atr = _atr, //复制到一个变量方便以后引用原值
            isie = !-[1,]; //判断是否是IE浏览器
        for(var i = 1; i < arr.length; i++) //从分割后得到的数组的第二个元素开始,将第一个字符大写
            arr[i] = arr[i].substring(0,1).toUpperCase() + arr[i].substring(1);
        atr = arr.join('');//重新将数组连接成一个字串
        switch(atr){
            case 'opacity':
                    isie ? node.style.filter = 'alpha(opacity='+css[_atr]*100+')' : node.style[atr] = css[_atr];//针对不同浏览器下的设置
                    break;
            case 'float':
                    isie ? node.style.styleFloat = css[_atr] : node.style.cssFloat=css[_atr];
                    break;
            default:node.style[atr] = css[_atr];
                    break;
        }
    }
}
 
/* 例子 */
var node= document.getElementById("node");
setNodeStyle(node,{ 'height':'200px',
                 width:'300px',
                margin-left:'20px',
                marginTop:'10px',
                'opacity':'0.8' }

其它方便的写法

其实有一个方法十分的方便,google的服务中很多都是使用这种写法,兼容性也十分好,从IE6到opera都支持良好。那就是cssText,如

node.style.cssText='height:200px;width:300px;background-color:red;'

就如同正常书写css代码一样,但是记住此处不要再使用驼峰写法了。

还有一个方法是使用setAttribute方法,如

node.setAttribute('style','height:200px;width:200px;background-color:red;')

这种写法也支持连写。

各种写法的优缺点

从代码量上看,“最基本的写法”所需的代码做多,函数封装后的代码次之,cssText和setAttribute写法所需代码量最少。

从性能上来看,由于函数封装和“最基本的写法”本质上是一样的,是一个一个样式设置的。我觉得每设置一个样式应该都会触发浏览器的一个现场更新,重绘页面。比如如果设置高度、宽度、背景色、透明度四个样式,那么就需要四次现场更新。所以此种写法应该是很不划算的。即是说已经有浏览器对这方面进行了优化,可以将短时间内的会引起现场更新的操作放到一个队列里,之后一起更新。但是保险起见,鉴于有更好的方法的话,尽量少用此种方法。

至于cssText和setAttribute这种连写方法,浏览器是如何处理的我不得而知,不过我觉得应该是将样式一次应用于节点,只需更新一次现场即可的。

所以我觉得还是使用cssText和setAttribute是比较好的(个人观点,欢迎反驳)。

更改节点样式的最佳模式

这里是讨论模式,而不是方法。我觉得基于尽量减少浏览器现场更新的思想,最好的做法的对节点设置类,然后在css中对这个类进行样式定义。比如还用上面的例子,将node节点样式设置为“高度200像素,宽度300像素,右浮动,背景颜色为红色”,我就可以用如下思路

//页面的.css文件中写入
.new{
    height:200px;
    width:300px;
    float:right;
    background-color:red;
}
 
//JavaScript代码
node.className += ' new';

这样通过一次现场更新就可以完成样式更新。要恢复默认样式就可以删除new这个类就行了。这种方法也可以降低css和JS的耦合度,如果你未来需要更新另一种样式,则只需修改css即可,JS不需要改动(JavaScript最佳实践思想)。

当然,对于需要较多次的样式修改,这种方法就有些繁琐了。至于如何选择,就需要我们在性能和简洁方面找到一个平衡点。

javascript

本文标签: , , , ,

分享

本文短网址: http://qiqi.boy.im/9u

这篇文章已经有 31 条评论

Comments (31) Trackbacks (0)
You can leave a response or Trackback this entry .
  1. liuqiqi -#1

    美美的沙发。。。 :oops:

  2. 丕子 -#2

    这里的节点是?

  3. winy -#3

    真给力的技术文,我居然看完了。只知道在讲啥

    • QiQiBoY --#1

      @winy
      。。。唔。。那还好,说明我写的思路还够清晰,没让别人越看越晕。。。 :grin:

  4. Alan -#4

    当然支持后两种写法啦 :arrow:

  5. 静夜燃香 -#5

    嗯,我知道这是一篇很有用的文,虽然只看懂了一点点点。。。去GR星一下~~

  6. 掌柜的马甲 -#6

    还是最后一种方法最好,看着顺服

  7. Ray Chow -#7

    我原来都是习惯匈牙利命名法的,可是后来CSS里面这么多杠杠,弄的我混乱了,现在JS命名也是毫无章法

  8. 唐人游博客活动 -#8

    尊敬的博主,您好!现在有个针对每个wordpress主题的博主有奖博客征文活动!欢迎您报名参加:http://happy.uc55.com/www/bloger/

  9. 一世年华 -#9

    :arrow: 我就是纯粹的过来水水。。。

  10. MOPVHS -#10

    思路真清晰~~~~赞~~~

  11. 小邪 -#11

    。。。。。翻来复去看了两遍半才理解 – - ~
    只不过,不大明白,在什么情况下要用js操纵如此多的css属性呢?
    感觉在css里面另外写个class,然后和原先的class相互切换应该会比较方便的说。 :?:

    • QiQiBoY --#1

      @小邪
      情况太多了,现在使用JS做开发的哪个项目里会碰不到呢。。。
      通过类方法更改样式当然不错,但是这种方法同时要麻烦些,同时要改写js文件和css文件。。。。
      所以我才在文末说到“需要在性能和简洁方面找到一个平衡点”,具体情况具体选择

    • 小邪 --#2

      @QiQiBoY
      哦,原来是这样,了解鸟。

  12. mice -#12

    看样子,你准备写个自用的jquery么..

  13. Glow -#13

    最近在学JS呢。

    博主的ajax主题真的很棒!

  14. yun77op -#14

    isie = !-[1,];真能判断ie?

  15. sking -#15

    判断ie的方式(![-1,])在最新的版本不再支持。。这样的方式炫耀下是可以的。。实用性太差

  1. No trackbacks yet.

Leave a Reply

Hi , say something.

  • :?:
  • :razz:
  • :sad:
  • :evil:
  • :!:
  • :smile:
  • :oops:
  • :grin:
  • :eek:
  • :shock:
  • :???:
  • :cool:
  • :lol:
  • :mad:
  • :twisted:
  • :roll:
  • :wink:
  • :idea:
  • :arrow:
  • :neutral:
  • :cry:
  • :mrgreen: