dojo/dom-style样式操作学习笔记

基础总结

  一个元素的样式信息由三个来源根据层叠规则确定。三个来源分别是:

  • 由DOM元素style特性设置的内联样式
  • 由style元素中嵌入的样式规则
  • 由link元素引入的外部样式表

  元素的样式

  任何支持style特性的HTML元素在JavaScript中都有一个对应的style属性。这个style对象是CSSStyleDeclaration的实例,包含着通过HTML的style特性指定的所有样式信息,但不包含与外部样式表或嵌入样式表经层叠而来的样式。在style特性中指定的任何css属性都可以通过这个style对象相应的属性来访问(对于短划线的css属性必须转化成驼峰形式:background-color=》backgroundColor)。除“float”外大部分css属性都可以通过简单转化为属性形式访问,因为float来JavaScript中属于保留字,所以在firefox、chrome、opera、safari等浏览器中对应JavaScript属性为cssFloat,而在Ie中对应为styleFLoat。

  “DOM2级样式”规范中为CSSStyleDeclaration对象定义了一系列的属性和方法(IE9+):

  • cssText:读取模式下返回浏览器对style特性中css代码的内部表示;写模式下,赋给cssText的值会重写整个style特性的值。设置cssText是为元素应用多项变化最快捷的方式。
  • length:应用给元素的css属性的数量
  • parentRule:表示css信息的CSSRule对象。
  • getPropertyCSSValue(propertyName):返回包含给定属性值的CSSValue对象。(CSSValue对象包含两个属性:cssText和cssValueType;cssText与getPropertyValue()返回的值相同)
  • getPropertyPriority(propertyName):如果给定的css属性使用了!important设置,则返回"!important";否则返回空字符串
  • getPropertyValue(propertyName):返回给定属性的字符串值
  • item(index):返回给定位置的CSS属性的名称
  • removeProperty(propertyName):从样式中删除给定属性
  • setProperty(propertyName, value, priorit):将给定属性设置为相应值,并加上优先权标识("!important"或者一个空字符串)

  元素的样式

  "DOM2级样式"增强了document.defaultView,defaultView指向当前文档所在的window对象。该对象增加了一个getComputedStyle(node, pseudo)方法,该方法返回一个CSSStyleDeclaration对象,包含当前元素的所有计算样式。而IE中并不支持该方法,与其对应的是node.style.currentStyle属性,该属性也是CSSStyleDeclaration的实例,包含当前元素所有计算后的样式。无论在哪个浏览器中,所有计算后的样式都是只读的。

  样式表

  CSSStyleSheet类型代表样式表,仅仅是样式表,无论是通过<link>元素包含的样式表和在<style>元素中定义的样式表。CSSStyleSheet对象是一套只读的接口(除了disabled属性)。CSSStyleSheet接口的属性如下:

  • disabled:布尔值,表示样式表是否被禁用。该属性是可读写的,设为true可以禁用样式表。
  • href:如果是通啊过<link>设置的则返回样式表的URL否则返回null
  • media:当前样式表支持的所有媒体类型的集合。
  • ownerNode:指向当前样式表的节点的指针;如果当前样式表是其他样式表通过@import导入的,该属性为null。IE不支持该属性。
  • parentStyleSheet:如果当前样式表是通过@import导入的情况下,这个属性是一个指向导入它的样式表的指针。
  • title:ownerNode的title。
  • type:表示样式表类型的字符串。对css样式而言,这个属性是"type/css"
  • cssRules:表示样式表中包含的样式规则的集合。IE不支持这个属性,但支持一个rules属性。
  • ownerRule:如果样式表是通过@import导入的,这个属性表示导入的规则。IE不支持该属性。
  • deleteRule(index):删除cssRules中指定位置的规则。IE不支持该属性,但支持类似的removeRule(index).
  • insertRule(rule, index):像cssRules集合中指定的位置插入rule字符串。IE不支持,但有一个类似的addRule()方法。

  也可以直接通过<link>或<style>元素取得CSSStyleSheet对象。element.sheet指向代表该元素样式表的CSSStyleSheet对象。IE中不支持该属性,但支持一个styleSheet属性。

  CSS规则

  CSSRule对象表示样式表中的一条规则。CSSStyleRule继承自CSSRule类,并提供了以下属性:

  • cssText:返回整条规则对应的文本。IE不支持这个属性
  • parentRule:如果当前规则是导入的规则,这个属性引用的就是导入规则;否则为null;IE不支持这个属性
  • parentStyleSheet:当前规则所属的样式表。IE不支持该属性。
  • selectorText:返回当前规则的选择符文本。这个属性是只读的。
  • style:一个CSSStyleDeclaration对象,可以通过它设置和取得规则中特定的样式值。
  • type:表示规则类型的常量。IE不支持。

  其中cssText、selectorText、style三个属性最常用,cssText与style.cssText属性类似,但cssText包含选择符文本和围绕样式信息的花括号,而style.cssText只有样式信息,style.cssText是可读写的而cssText是只读的。

  这几种类型的关系如下图所示:

  dojo/dom-style

  该模块提供两个方法:get和set。

  对于取值,最重要的是获取样式层叠之后的计算值,所以要使用的原生api就是getComputedStyle。但是该函数有兼容性问题,上文提到过IE中没有该方法,只能通过element.currentStyle来达到相同的效果;另外,webkit内核浏览器中如果node的display为none,这时调用getComputedStyle是无法取到正确结果的,这里dojo自己处理了一下将其diaplay设为空字符串。一下便是dojo中对getComputedStyle的处理:

var getComputedStyle, style = {
        // summary:
        //        This module defines the core dojo DOM style API.
    };
    // nodeType为1,代表元素节点
    if(has("webkit")){
        getComputedStyle = function(/*DomNode*/ node){
            var s;
            if(node.nodeType == 1){
                var dv = node.ownerDocument.defaultView;
                s = dv.getComputedStyle(node, null);
                // node不可见时,无法得到有效结果
                if(!s && node.style){
                    node.style.display = "";
                    s = dv.getComputedStyle(node, null);
                }
            }
            return s || {};
        };
    }else if(has("ie") && (has("ie") < 9 || has("quirks"))){
        getComputedStyle = function(node){
            return node.nodeType == 1 && node.currentStyle ? node.currentStyle : {};
        };
    }else{
        getComputedStyle = function(node){
            return node.nodeType == 1 ?
                node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
        };
    }
    style.getComputedStyle = getComputedStyle;

  到这里我们仅仅能得到计算后的样式值,但getComputedStyle方法的样式值是带有单位的,而实际应用中我们往往需要的是数字值。所以接下来的步骤就是将计算值转化成数字:

var toPixel;
    if(!has("ie")){
        toPixel = function(element, value){
            //非ie浏览器直接转化成数字
            return parseFloat(value) || 0;
        };
    }else{
        // ie浏览器下则要进行各种兼容处理
        toPixel = function(element, avalue){
            if(!avalue){ return 0; }
            // 对于border-width 可能设置为medium,这时我们认为宽度为4
            if(avalue == "medium"){ return 4; }
            // 带px单位的,去掉px即可;slice函数参数为负数的相当于length+负数
            if(avalue.slice && avalue.slice(-2) == ‘px‘){ return parseFloat(avalue); }
            // 下面这段没看懂。。。。。
            var s = element.style, rs = element.runtimeStyle, cs = element.currentStyle,
                sLeft = s.left, rsLeft = rs.left;
            rs.left = cs.left;
            try{
                // ‘avalue‘ may be incompatible with style.left, which can cause IE to throw
                // this has been observed for border widths using "thin", "medium", "thick" constants
                // those particular constants could be trapped by a lookup
                // but perhaps there are more
                s.left = avalue;
                avalue = s.pixelLeft;
            }catch(e){
                avalue = 0;
            }
            s.left = sLeft;
            rs.left = rsLeft;
            return avalue;
        };
    }
    style.toPixelValue = toPixel;

  处理完这些之后,让我们先看一下dojo/dom-style.get方法:

style.get = function getStyle(/*DOMNode|String*/ node, /*String?*/ name){
        var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
        // 对于opacity做兼容处理,非ie直接使用css中的opacity属性; ie8以下浏览器并不支持,这时就需要使用滤镜,所以取值时候也要特殊处理
        if(l == 2 && op){
            return _getOpacity(n);
        }
        // 对于float保留字的处理,非ie用的是CSSFloat而ie使用的是styleFloat
        name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
        var s = style.getComputedStyle(n);
        // 如果指定的属性名称,调用_toStyleValue方法。
        return (l == 1) ? s : _toStyleValue(n, name, s[name] || n.style[name]); /* CSS2Properties||String||Number */
    };

  dojo中对于opacity做了兼容性处理,这里我们只要知道原理即可,想详细了解的同学可以自己查看dojo源码:

var astr = "DXImageTransform.Microsoft.Alpha";
    var af = function(n, f){
        try{
            return n.filters.item(astr);
        }catch(e){
            return f ? {} : null;
        }
    };

    var _getOpacity =
        has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(node){
            try{
                return af(node).Opacity / 100; // Number
            }catch(e){
                return 1; // Number
            }
        } :
        function(node){
            return getComputedStyle(node).opacity;
        };

    var _setOpacity =
        has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(/*DomNode*/ node, /*Number*/ opacity){
            if(opacity === ""){ opacity = 1; }
            var ov = opacity * 100, fullyOpaque = opacity === 1;

            // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
            // but still update the opacity value so we can get a correct reading if it is read later:
            // af(node, 1).Enabled = !fullyOpaque;

            if(fullyOpaque){
                node.style.zoom = "";
                if(af(node)){
                    node.style.filter = node.style.filter.replace(
                        new RegExp("\\s*progid:" + astr + "\\([^\\)]+?\\)", "i"), "");
                }
            }else{
                node.style.zoom = 1;
                if(af(node)){
                    af(node, 1).Opacity = ov;
                }else{
                    node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
                }
                af(node, 1).Enabled = true;
            }

            if(node.tagName.toLowerCase() == "tr"){
                for(var td = node.firstChild; td; td = td.nextSibling){
                    if(td.tagName.toLowerCase() == "td"){
                        _setOpacity(td, opacity);
                    }
                }
            }
            return opacity;
        } :
        function(node, opacity){
            return node.style.opacity = opacity;
        };

  通过上面代码我们可以看到,如果没有获取特定属性直接返回getComputedStyle方法得到的结果,如果指明特定属性则调用_toStyleValue方法, 该方法决定将哪些值转化成数字:

var _pixelNamesCache = {
        left: true, top: true
    };
    // 如果获取的属性符合这个正则表达式,将他们放到_pixelNamesCache中,将得到的结果转化成数字
    var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border
    function _toStyleValue(node, type, value){
        //TODO: should we really be doing string case conversion here? Should we cache it? Need to profile!
        type = type.toLowerCase();
        if(has("ie") || has("trident")){
            //ie浏览器中如果width或height得到的是auto,使用offsetWidth或者offsetHeight
            if(value == "auto"){
                if(type == "height"){ return node.offsetHeight; }
                if(type == "width"){ return node.offsetWidth; }
            }
            // 对fontWeight的处理
            if(type == "fontweight"){
                switch(value){
                    case 700: return "bold";
                    case 400:
                    default: return "normal";
                }
            }
        }
        //如果符合正则,则放入_pixelNamesCache中,将得到的结果转化成数字
        if(!(type in _pixelNamesCache)){
            _pixelNamesCache[type] = _pixelRegExp.test(type);
        }
        return _pixelNamesCache[type] ? toPixel(node, value) : value;
    }

  

  有了以上基础,设置就简单许多:

style.set = function setStyle(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
        var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
        // 对float属性的处理
        name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
        // 处理opacity属性
        if(l == 3){
            return op ? _setOpacity(n, value) : n.style[name] = value; // Number
        }
        // 如果一次设置多个属性,将他们分别处理;
        for(var x in name){
            style.set(node, x, name[x]);
        }
        // 返回样式的计算值
        return style.getComputedStyle(n);
    };

   对于多个属性处理的这部分,最好的方式是使用cssText一次设置多个值:style.cssText = style.cssText+"拼接后的样式字符串"。这样浏览器只需要重新绘制一次即可应用多种样式。而不是每次设置style都要重绘一次(有的浏览器可以做优化处理)。当然使用cssText方式,一来在ie8中并不支持,而来如果要重新覆盖一个样式属性我们还需要做一些处理。

  以上部分就是今天的博客内容,如果您觉得这篇文章对您有帮助,请不吝点击下方推荐,您的鼓励是我分享的动力!!!

  

时间: 2024-10-17 21:14:52

dojo/dom-style样式操作学习笔记的相关文章

DOM Style样式对象的详细用法

DOM Style样式对象的详细用法 HTML Style样式比较复杂,相应访问.修改方法也有所差异.参考相关资料,整理如下. 典型Html文件如下,有三种定义方式. <head>     <style type="text/css">                /* 内部样式 */       h3 {color:green;}     </style>             <!-- 外部样式 style.css -->    

《javascript DOM 编程艺术》学习笔记(一)

书籍已经看完了前六章的内容,有了一定的编程基础后觉得本书内容相对来说过于简单,应该是完全针对于初学者的(或者如作者所说是写个Web设计师的),作者在表述一个问题,一句代码都解释得非常啰嗦与重复,不过从书中学习到更多的,也是作者想让读者体会的是让大家理解DOM脚本编程技术背后的思路和原则,作者特别以早期Javascript的滥用来强调Web的规范与标准,这一点是非常值得学习的,也是一个程序员的基本素养. 截止到第六章,将所学到的知识点归纳如下: 1.基本语法:与php一样是弱类型语言,虽然功能强大

MySQL4.0命令操作学习笔记

声明:下列内容并非原创,仅仅是最近学习笔记整理. -------------------------------------- 进入mysql安装路径bin目录下: 1.开启服务 winmysqladmin.exe 回车按照提示: 输入winmysqladmin初始用户.密码(注:mysql里用户.密码)随便填必意 2.根目录密码重置 mysqladmin -u root -p password 123456 回车出现 Enter password: ( 注:叫输入原密码. 刚安装时密码空,所直

Winform操作Access数据库增删改操作学习笔记

此程序是本人学习Winform操作Access数据库时学习笔记. 程序源码来源于:<Visual C# 2008 程序开发入门与提高 >赵增敏 编著 操作方法: 1.新建一个Winform项目,并将该项目设置为启动项目: 2.复制数据库文件到程序根目录下. 3.添加3个Label.两个TextBox.一个ListBox,四个Button控件. 4.窗体底部Label修改名称为“labelMsg”,两个文本框修改名称为:textboxSurname,textboxName. 5.列表框命名为Li

DOM编程性能优化学习笔记

参考高性能javascript  javascript编程全解 1)DOM 文档对象模型是一种操作xml和html文档的接口(API),我们可以通过javascript(ECMAScript)访问DOM,访问或者修改DOM的时候会产生开销,接下来讨论如何减少这方面的开销 这里面想到了几种方案 1)减少DOM的访问次数 使用局部变量 2)创建新的节点的时候 clone已经存在的节点  使用能区分元素节点和其他节点的属性  使用选择器API(这3种优化了方法,使用了不同于之前的方法) 3)最小化重绘

dom文档操作-学习

今天出门,发现家猫,吐在我的鞋子上.猫猫觉得我不紧要当铲屎官还要当擦鞋官啊. 上次用css和html做了个防站酷的静态首页后,觉得现在改学学文档操作了.上w3c看了下文档操作. 大致理解操作步骤, 1.通过浏览器window对象,获取里面的熟悉document,这个表示当前文档对象, 2.获取document后,document里面有三个核心方法:getElementByClass,getElementByName,getElementByTag,姑且称为getElement三兄弟吧. 3.然后

表的连接操作(学习笔记)

在数据库中对于数据表的连接操作一共提供了两种: 内连接:也称等值连接在where中消除笛卡尔积的条件就是采用了内连接方式进行的 外连接: 内连接中只能显示等值满足的条件,不满足的条件则无法显示,如果希望显示特定表中的全部数据就要用要外连接 外连接分3种    在Oracle中使用(+)表示连接 左外连接(左连接) 左关系属性=右关系属性(+) 表示左外连接 右外连接(右连接) 左关系属性(+)=右关系属性 表示右外连接 全外连接(全连接) 示例一 (内连接) 将emp和dept表联合查询 SEL

PHP字符串操作学习笔记

由于PHP是弱语言类型,所以当使用字符串操作函数是,其他类型的数据也会被当作字符串来处理. 一.字符串定义与显示 字符串通过单引号.双引号来标志,前者将单引号内所有的字符都当作字符来处理,后者则不是. 字符串的显示可以使用echo()和print()函数,二者区别:print()具有返回值,返回1,而echo()则没有,所以echo()比print()要快一些,print()能应用于复合语句中,而echo()不能.另外echo可以一次输出多个字符串,而print不可以. 二.字符串的格式化 函数

Spark的transformation 和 action的操作学习笔记

一.spark的transformation 和 action区别 Spark有一些基本的transformation 和 action的操作,其中transformation形成各类型的RDD,action不形成RDD,而是对RDD进行累加.合并.保存操作. 二.transformation 有哪些 transformation有map.filter.flatMap(与map不一样).Sample.groupByKey.ReduceByKey.Union.Join.cogroup.crossP