博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dojo/dom-class源码学习
阅读量:6681 次
发布时间:2019-06-25

本文共 6407 字,大约阅读时间需要 21 分钟。

  dom-class模块是dojo中对于一个元素class特性的操作(),主要方法有:

  • contains 判断元素是否包含某个css class
  • add 为元素添加某个css class
  • remove 移除某个css class
  • replace 用某个css class取代另一个css class
  • toggle 开关某个css class

 

  对于支持classList的浏览器可以使用calssList提供的方法,但支持这个属性的浏览器很少,貌似只有firefox和chrome支持。dojo这里使用了通用的方法:更改className的值。

// example:            //        Add two classes at once:            //    |    require(["dojo/dom-class"], function(domClass){
// | domClass.add("someNode", "firstClass secondClass"); // | }); // // example: // Add two classes at once (using array): // | require(["dojo/dom-class"], function(domClass){
// | domClass.add("someNode", ["firstClass", "secondClass"]); // | });

  该模块中的许多方法,比如add、remove、replace既可以添加一个连续的class字符串(类与类之间使用空格相连:"class1 class2 class3")也可以添加class数组。在dojo内部的处理中,全部将“class1 class2 class3”这种形式转化成数组。就是str2Array方法:

var cls, // exports object        spaces = /\s+/, a1 = [""];    function str2array(s){        if(typeof s == "string" || s instanceof String){            // 单个字符串            if(s && !spaces.test(s)){                a1[0] = s;                return a1;            }            var a = s.split(spaces);            // 去除前面的空白字符,如:“ string”            if(a.length && !a[0]){                a.shift();            }            // 去除后面的空白字符,如:“string ”            if(a.length && !a[a.length - 1]){                a.pop();            }            return a;        }        // assumed to be an array        if(!s){            return [];        }        // 普通数组        return array.filter(s, function(x){ return x; });    }

  按我的理解去除前后空白字符的过程有些啰嗦,dojo/_base/lang模块有trim方法,就是用来去除前后空白字符。这里完全可以直接调用,看来不是一个人写的。

  

  contains、add、remove这三个函数属于这个模块中的基础方法,理解这个模块的代码还要知道一个核心原理是:这些方法全部为className和新class的头尾新加空格: " class1 class2 class3 "; " newClass ",利用字符串操作的方式来处理,这样既可以提高处理效率又能有效避免浏览器多次重绘引发的性能问题。

  先看一下contains方法:

contains: function containsClass(/*DomNode|String*/ node, /*String*/ classStr){            // summary:            //        Returns whether or not the specified classes are a portion of the            //        class list currently applied to the node.            // node: String|DOMNode            //        String ID or DomNode reference to check the class for.            // classStr: String            //        A string class name to look for.            // example:            //        Do something if a node with id="someNode" has class="aSillyClassName" present            //    |    if(dojo.hasClass("someNode","aSillyClassName")){ ... }            return ((" " + dom.byId(node)[className] + " ").indexOf(" " + classStr + " ") >= 0); // Boolean        },

  将className与classStr首尾都添加空格后,利用String类型的indexOf方式来判断是否存在classStr。

add: function addClass(/*DomNode|String*/ node, /*String|Array*/ classStr){            node = dom.byId(node);            //转化为数组            classStr = str2array(classStr);            var cls = node[className], oldLen;            // 添加空格字符            cls = cls ? " " + cls + " " : " ";            oldLen = cls.length;            // classStr挨个判断,不存在与cls中的就添加进去            for(var i = 0, len = classStr.length, c; i < len; ++i){                c = classStr[i];                if(c && cls.indexOf(" " + c + " ") < 0){                    cls += c + " ";                }            }            // cls改变的话就使用新的className            if(oldLen < cls.length){                node[className] = cls.substr(1, cls.length - 2);// 去除首尾的空白字符            }        }
remove: function removeClass(/*DomNode|String*/ node, /*String|Array?*/ classStr){            node = dom.byId(node);            var cls;            if(classStr !== undefined){                //这里与add方法中的思路类似                classStr = str2array(classStr);                cls = " " + node[className] + " ";                for(var i = 0, len = classStr.length; i < len; ++i){                    // 将classStr中的class移除掉                    cls = cls.replace(" " + classStr[i] + " ", " ");                }                cls = lang.trim(cls);            }else{ // 没有第二个参数则将所有class都移除掉                cls = "";            }            if(node[className] != cls){ node[className] = cls; }        }

  下面介绍replace方法,顾名思义替换,替换的方式通常都是先删除再添加。如果对于同一个节点删除、添加 class会引起浏览器重绘,所以这里引入了fakeNode来降低浏览器重绘次数,提高性能。

replace: function replaceClass(/*DomNode|String*/ node, /*String|Array*/ addClassStr, /*String|Array?*/ removeClassStr){            node = dom.byId(node);            //利用fakeNode避免移除、添加过程中浏览器重绘            fakeNode[className] = node[className];            cls.remove(fakeNode, removeClassStr);            cls.add(fakeNode, addClassStr);            if(node[className] !== fakeNode[className]){                node[className] = fakeNode[className];            }        }

  toggle方法可以对一组class进行开关控制,存在则删除,没有则添加。

toggle: function toggleClass(/*DomNode|String*/ node, /*String|Array*/ classStr, /*Boolean?*/ condition){            node = dom.byId(node);            if(condition === undefined){                classStr = str2array(classStr);                for(var i = 0, len = classStr.length, c; i < len; ++i){                    c = classStr[i];                    cls[cls.contains(node, c) ? "remove" : "add"](node, c);                }            }else{                cls[condition ? "add" : "remove"](node, classStr);            }            return condition;   // Boolean        }

  看dojo的实现方式,使用toggle对一组class开关操作时会导致浏览器多次重绘,我们完全可以对className和classStr做差异融合,然后一次替换,或者像replace中一样,利用fakeNode来防止多次重绘。

toggle: function toggleClass(/*DomNode|String*/ node, /*String|Array*/ classStr, /*Boolean?*/ condition){            node = dom.byId(node);            if(condition === undefined){                classStr = str2array(classStr);                                fakeNode[className] = node[className];// 利用fakeNode防止多次重绘                                for(var i = 0, len = classStr.length, c; i < len; ++i){                    c = classStr[i];                    cls[cls.contains(node, c) ? "remove" : "add"](fakeNode, c);                }                                // 一次重绘                if(node[className] !== fakeNode[className]){                    node[className] = fakeNode[className];                }            }else{                cls[condition ? "add" : "remove"](node, classStr);            }            return condition;   // Boolean        }
如果您觉得这篇文章对您有帮助,请不吝点击右下方“推荐”,谢谢~

转载地址:http://oinao.baihongyu.com/

你可能感兴趣的文章
SQL Server误区30日谈-Day21-数据损坏可以通过重启SQL Server来修复
查看>>
深入了解Hive Index具体实现
查看>>
一年又一年[2013开始了]
查看>>
C primer笔记
查看>>
Java多态之重写<一>
查看>>
android 问题汇总系列之八
查看>>
线程优先级
查看>>
【css】纯 css 制作带三角(border篇)
查看>>
MySQL数据库服务器优化详细
查看>>
Socket异步通信——使用SocketAsyncEventArgs
查看>>
alfresco_百度百科
查看>>
导入Excel数值读不到,找不到可安装的 ISAM错误
查看>>
[xcode]安装xcode出现一个错误:The Installation Failed.
查看>>
Mysql:bit类型的查询与插入
查看>>
poj2551
查看>>
手动爆库详细流程以及语句解析
查看>>
java模式之装饰模式
查看>>
ubuntu13.04下载android4.0.1源码过程
查看>>
【编程珠玑】读书笔记 第二章 算法
查看>>
百度搜索结果页url参数详解
查看>>