HTML5 DOM元素类名相关操做API classList简介(转载自张鑫旭大神)

1、其实事情的发展就像切水果

若是咱们把元素的类名操做比做“切水果”游戏的话,其中一个单独的类名就比如“水果”或“炸弹”!android

DOM Level 2时代,类名的获取与设置,多半使用className属性,className的生效近似切水果的“一刀切”。在web的初期,交互什么的其实很简单的来;就像切水果刚开始的时候,一次就一个水果飞上来,一刀“咔嚓”切了就好,就像使用className赋个类名值,就算偶尔冒出2个水果,className也能够一刀切搞定的。ios

可是,随着web的发展,交互的逐渐复杂,一次出现的水果愈来愈多,已经不是className一刀就能够搞定的了;并且,还有炸弹,className一刀切可能就自寻死路了。web

为了应对这种需求,显然HTML5要作点什么,因而classList API出现了,能够有针对性地切水果,不会碰到炸弹什么的……数组

这就是事情从className发展到classList的原因与过程。浏览器

classList虽改进,可是,从效果上讲,仍是敌不过jQuery等外挂,后面会提到。app

2、浏览器们,大家怎么看?

classList实际上已经出现好多年了,所以,天然,FireFox浏览器,Chrome浏览器都支持的很。IE家族中,从IE10浏览器开始才开始承认classList能进能退的非一刀切作法。框架

手机上,Android 3.0+以上才开始支持,哦,该死,这很糟糕。如今手机web app要求android 2.*也要支持。dom

截止今日,兼容性见下截图:函数

因而可知,在PC上,若是要判断是不是IE10+以及其余现代浏览器,能够试试:document.body.classList是否为undefined学习

3、classList API概要

假设有这么个空白页面:

<body class="a b c"></body>

在Firebug以及Chrome控制台中,运行:

document.body.classList

返回的分别是:

可见其直接暴露的API有:

  • length 属性,表示元素类名的个数,只读
  • item() 支持一个参数,为类名的索引,返回对应的类名,例如上例:
    document.body.classList.item(0);

    结果是:"a".

    若是索引超出范围,例如:

    document.body.classList.item(3);

    结果是:null.

  • add() 支持一个类名字符串参数。表示往类名列表中新增一个类名;若是以前类名存在,则添加忽略。例如:
    document.body.classList.add("c");
    document.body.classList.length    // 3

    此函数方法执行的返回值是undefined, 所以,classListadd()方法是没法级联的。下面的remove()方法也是如此。

  • remove() 支持一个类名字符串参数。表示往类名列表中移除该类名。例如:
    document.body.classList.remove("c");
    document.body.classList.length    // 2

    有点对应于jQuery中的removeClass()方法,而后者返回包装器对象自己,可级联;这里的remove()方法返回undefined.

  • toggle() 支持一个类名字符串参数。无则加勉,有则移除之意。若类名列表中有此类名,移除之,并返回false; 若是没有,则添加该类名,并返回true.

    更新于当日
    部分现代浏览器,例如Chrome浏览器以及Firefox 24的toggle()方法已经支持第2个参数,.toggle(token, switch). 其中参数switch为Boolean类型值,若是为true表示添加,若是为false则表示移除。并返回该Boolean值。

  • contains() 支持一个类名字符串参数。表示往类名列表中是否包含该类名。有点对应jQuery中的hasClass方法,注意,这里的是contains而不是contain,后面有个s哦!

    返回值很易懂的。若是包含,则返回true, 不包含,则false. 例如:

    document.body.classList.contains("c");    // false 由于"c"上面remove掉了

在Firebug控制台结果中,咱们还看到了toString()方法。实际上,Chrome浏览器也有(未直接显示),IE10也有,不过,彷佛来自层级更高对象的继承。从下面截图中的属性颜色区分可见一斑:

就做用上讲,等同于className. 例如:

document.body.classList.toString() === document.body.className; // true

4、classList的本质-DOMTokenList

classList的返回值显示,其本质上是DOMTokenList – DOM标记列表.

DOMTokenList这种类型表示一组空间分隔的标记。一般由HTMLElement.classListHTMLLinkElement.relList,HTMLAnchorElement.relListHTMLAreaElement.relList返回。从0开始的类JavaScript数组索引。DOMTokenList始终是区分大小写的。

在FireFox以及Chrome下,咱们执行typeof DOMTokenList的结果是:"function"; 可是在IE10下,倒是:"object".

同时虽然typeof结果为"function",可是执行DOMTokenList()会报”Illegal constructor”错误;IE10执行DOMTokenList()也会报错,错误是”缺乏函数”。

所以,试图经过typeof obj == "function"来判断obj就是个函数的作法是不彻底正确的。

5、classList的局限

classList除了上面提到的不能级联这个无关痛痒的局限外,还有个比较头疼的局限,就是不能一次addremovetoggle多个类名。//zxx: 级联指的是$().a().b().c()这种能够连在一块儿调用方法的写法。

例如:

document.body.classList.add("c d");    // Error: String contains an invalid character
document.body.classList.add("c\x20d");   // Error: String contains an invalid character
document.body.classList.remove("c d");    // Error: String contains an invalid character

咱们要想多类名处理,须要一个一个来,例如:

var clList = document.body.classList;
clList.add("d");
clList.add("e");
clList.toString(); // "a b c d e"

多个类名添加的处理 张鑫旭-鑫空间-鑫生活

这一点来看,原生的classList API要比jQuery或MooTools等框架的addClass/removeClass/...等类名相关外挂方法弱爆了。然而,classList API没有恋爱经历、很是单纯。所以,虽然胸小了一点;可是,富豪就是喜欢之。

6、classList的扩展

add的参数个数限制等方法比如生孩子,一次只能生一个,这符合国家要求符合规范。可是,有些有钱人,就像张艺谋,就愁孩子少,恨不能一次生他3个,咋办呢?咱们能够试试对classList作扩展,例如扩展一个adds方法,能够一次添加多个类名,多个类名以空格分隔:

DOMTokenList.prototype.adds = function(tokens) {
   tokens.split(" ").forEach(function(token) {
       this.add(token);
   }.bind(this));
   return this;
};

// 看看能不能一会儿生3个孩子
var clList = document.body.classList;
clList.adds("child1 child2 child3").toString(); // "a b c child1 child2 child3"

DOMTokenList方法扩展-多类名添加示意

这样,只要肚子够大,想生几个就能够生几个了,中国足球说不定就有但愿了——11胞胎争霸全球!

其余些方法,您能够作相似扩展。

可是,平心而论,单类名一个一个添加虽然苦逼了点,可是,我的情感上,由于原汁原味,更喜欢!

//zxx: ios4彷佛并未支持bind方法,所以,上面的扩展若是在手机上使用,需稍做调整。

7、结语

随着JS API的愈来愈丰富,以及愈来愈多在现代浏览器、尤为手机上的一些折腾,让我愈来愈疑惑一些庞大框架的存在乎义。

有人可能会提出:原生的API方法名太长了,例如:addEventListenergetComputedStyleinsertAdjacentHTML,getBoundingClientRect等。

我:“而后呢……”
“名字长,很差记啊……”
我:“没错,而后呢……”
“文件大啊……”
我:“保留,而后呢……”
“新人很差上手啊……”
我:“算是,而后呢……”
“……”
我:“没话说了吧,那我来讲!”

1. 关于“名字长,很差记”
你父母手机号是?啊,不知道啊!那确实名字太长,不太好记。

2. 关于“文件大啊”
小明工做40年,交的养老保险金有100万,0存款,每月能够拿4000, 每个月结余2000; 大明工做40年,养老保险一分钱没交,存了100万,每个月结余-3000。结果,小明笑大明每月的开销比他多1000块,说你没交养老保险亏大了。

dom.addEventListener$(dom).bind哪一个字符多,显然前者,小明你赢了!

那下面代码呢?

var addEventListener = "addEventListener";
dom[addEventListener]

var bind = "bind";
$(dom)[bind]

小明,你又赢了!JS压缩以后呢?

var a= "addEventListener";
dom[a]

var b= "bind";
$(dom)[b]

小明,你又赢了!那多调用几回呢?

var a= "addEventListener";
dom[a]
dom[a]
dom[a]
dom[a]
dom[a]

var b= "bind";
$(dom)[b]
$(dom)[b]
$(dom)[b]
$(dom)[b]
$(dom)[b]

同样多,小明,你还没输!好吧,我再次认为你是对的。

3. 关于“新人很差上手”
林远图封装了《葵花宝典》,美名曰“辟邪剑法”,比较好上手,结果呢,其儿孙泛泛。却是林平之,学习了盗版原生的《葵花宝典》,虽然很差上手(要咬抹布挥刀那个),可是,结果秒了余沧海,也算高手之列了。

啊?原来你是招新人来打杂的,sorry, 网上的框架、插件确实比较适合大家。

zepto.js算是蛮简洁的移动框架了,实际上,zepto.js有借鉴jqmobi.js(以前被intel收购,更名为appframework)的嫌疑(纠正:zepto.js是被jqmobi.js借鉴),然后者彷佛更小,我看了下,gzip后6.7K, 小于前者9.7k(因含touch相关事件重写). 可是,我我的看来,仍是太大了,尤为那些DOM相关的API,都统统会娘家去吧,gzip后2~3K足矣。

天气很热,想钓鱼了!

转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]

相关文章
相关标签/搜索