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 objectspaces = /\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 arrayif(!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改变的话就使用新的classNameif(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}
如果您觉得这篇文章对您有帮助,请不吝点击右下方“推荐”,谢谢~

dojo/dom-class源码学习相关推荐

  1. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  2. VUE源码学习第一篇--前言

    一.目的 前端技术的发展,现在以vue,react,angular为代表的MVVM模式以成为主流,这三个框架大有三分天下之势.react和angular有facebook与谷歌背书,而vue是以一己之 ...

  3. Vue源码学习 - 组件化一 createComponent

    Vue源码学习 - 组件化一 createComponent 组件化 createComponent 构造子类构造函数 安装组件钩子函数 实例化 VNode 总结 学习内容和文章内容来自 黄轶老师 黄 ...

  4. php连接tidb,TiDB源码学习笔记:启动TiDB

    作者:院长,神州数码云基地开发工程师,目前专注于TiDB源码研究. TiDB源码研究系列第一篇,简述TiDB的核心架构,从tidb-server/mian.go开始,探索启动TiDB的方法. 最近因为 ...

  5. 【iScroll源码学习01】准备阶段 - 叶小钗

    [iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文  http://www.cnblogs.com/yexiaochai/p/3 ...

  6. Vue源码学习 - 准备工作

    Vue源码学习 - 准备工作 准备工作 认识Flow 为什么用 Flow Flow 的工作方式 类型推断 类型注释 数组 类和对象 null Flow 在 Vue.js 源码中的应用 flow实践 总 ...

  7. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

  8. Shiro源码学习之一

    一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...

  9. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  10. 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制

    Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...

最新文章

  1. “期待已久的UFO报告”公布了
  2. Castle.ActiveRecord的ProxyFactory配置
  3. Python基础教程---读书笔记四
  4. 封装getByClass(JS获取class的方法封装为一个函数)
  5. [导入]C#中TextBox只能输入数字的代码
  6. zookeeper数据结构及Znode类型
  7. 龙果充值平台,具备话费充值、流量充值、话费卡兑换功能;可以拓展其他充值兑换业务;也适用于支付、鉴权等业务功能的拓展。
  8. 代码块作用域内外的静态变量
  9. Maven dependencyManagement 详解
  10. web登录框,div半透明
  11. linux与pe到移动硬盘,几步把WinPE安装到移动硬盘上
  12. 企业邮箱的优势有哪些?使用企业邮箱的好处
  13. STM32H7学习继续(STM32H7系列9) ADC
  14. 脑机接口、开源和民主化增强意识的未来
  15. Zabbix最新6.2安装及使用!
  16. replace语句的使用---鸡肋命令
  17. 吸波材料衰减常数计算,Excel源代码
  18. 因子分析(Factor Analysis)
  19. esp8266点灯LCD12864心知天气+农历+空气质量ArduinoJson6
  20. bc vc投资_【融资系列】 VC投资中的常见分期追加投资

热门文章

  1. Eclipse学习笔记——快捷键
  2. HDU 2553 N皇后问题 DFS 简单题
  3. iOS多线程技术—多线程简单介绍
  4. 三句话教你买对房子!买到好房子的都祝福哥三年内赚两个亿!
  5. Dedecms之SQL语句修改和调用数据总结
  6. 防雷探测器在建筑物中的要求
  7. Osql\sqlcmd工具管理 SQL Server
  8. Mac 版 Android Studio 汉化教程 及汉化包
  9. Linux-安装python3环境
  10. P4980 【模板】Polya定理