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

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

如果我们把元素的类名操作比作“切水果”游戏的话,其中一个单独的类名就好比“水果”或“炸弹”!

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

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

为了应对这种需求,显然HTML5要做点什么,于是classList API出现了,可以有针对性地切水果,不会碰到炸弹什么的……

这就是事情从className发展到classList的缘由与过程。

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

二、浏览器们,你们怎么看?

classList实际上已经出现好多年了,因此,自然,FireFox浏览器,Chrome浏览器都支持的很。IE家族中,从IE10浏览器开始才开始认可classList能进能退的非一刀切做法。

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

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

由此可见,在PC上,如果要判断是否是IE10+以及其他现代浏览器,可以试试:document.body.classList是否为undefined

三、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

四、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就是个函数的做法是不完全正确的。

五、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没有恋爱经历、非常单纯。因此,虽然胸小了一点;但是,富豪就是喜欢之。

六、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"

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

其他些方法,您可以做类似扩展。

但是,平心而论,单类名一个一个添加虽然苦逼了点,但是,个人情感上,因为原汁原味,更喜欢!

//zxx: ios4似乎并未支持bind方法,因此,上面的扩展如果在手机上使用,需稍作调整。

七、结语

随着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]

时间: 2024-08-10 02:10:35

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

[转] HTML5终极备忘大全(图片版+文字版)----张鑫旭

by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1544 一.前言兼图片备忘 下图是我从testking网站上的Ultimate HTML5 Cheatsheat这篇文章中备忘图片(已大小优化,因为图片较高,故滚动显示). 但是,上面毕竟是图片格式(原图上兆),而且还是英文的,所以自己觉得有必要将上面的内容文字化,同时做下简单的中文翻译.整理一番,于是就有下面的些内容.

web页面相关的一些常见可用字符介绍——张鑫旭

by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1623 正文开始之前先分享两个与字符相关的东西.首先是一张图片,是一张一些字符以及想对应的HTML实体表示的对照图片.如下: 然后是一个页面,是我收集的些杂七杂八字符页面,地址如下:http://www.zhangxinxu.com/sp/character.html 希望这两个东西能对您有所帮助,ok,下面是本文的主要

【转载】张鑫旭对知乎前端相关问题的十问十答

问题一.前端现在怎么这么多人? 原问题地址是:https://www.zhihu.com/question/55886635 问题描述如下: 投出去的简历没有人看了 我的回答: 想来想去,还是从一个非前端领域的切身故事说起吧. 我的老家江苏泰兴是中国银杏之乡,产量全国1/3,而我外公家宣堡镇除了小馄饨出门,还是就是中国银杏第一乡的美称.在我小的时候,银杏的药用价值和使用价值被发掘,银杏价格突然猛增,那个时候的银杏树是没有人专门种植的,全部都是很早很早以前的那些老树,百年以上的比比皆是,或者说全部

移动端测试——APP元素信息[事件]操作API和APP模拟手势高级操作(4)

appium基础API 1.1 APP元素信息操作API 介绍手机端元素信息的获取以及基本的输入操作 前置代码 # 导入driver对象 from appium import webdriver import time # server 启动参数 desired_caps = {} # 设备信息(系统.版本.设备号) desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '9' desired_cap

不使用JavaScript让IE浏览器支持HTML5元素——张鑫旭

by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=2515 如果我们不做什么手脚的话,IE6~IE8浏览器不支持HTML5元素, <nav>, <header>, <footer>, <article> … 然而,前篇Google前端规范HTML部分中提到:要使用语义的HTML5元素作为text/html, 考虑到Google不可能把

视区相关单位vw, vh..简介以及可实际应用场景——张鑫旭

一.N多的唠哩唠叨 CSS3中一些新的单位早在去年春暖花开的时候就介绍了,参见:CSS长度值及时间.频率.角度单位.显然,其中就提到了本文要感叹的单位vw, vh,见下图: 不过“我看见你”和“我触碰你”是不一样的.正好,机缘巧合,最近又与这两个单位想见.大致琢磨了下,貌似vh这个单位可以实现我以前曾希望实现的的整体高度自适应布局.想到这里,自己不由得小兴奋了下,于是决定抽时间研究研究(虽然最近整iPad忙得屁股尿流~~). 然而…… //zxx: 先卖个关子,一点一点唠叨来~~ vw, vh这

HTML5扩展之微数据与丰富网页摘要——张鑫旭

一.微数据是? 一个页面的内容,例如人物.事件或评论不仅要给用户看,还要让机器可识别.而目前机器智能程度有限,要让其知会特定内容含义,我们需要使用规定的标签.属性名以及特定用法等.举个简单例子,我们使用<h1>标签包裹页面标题信息就是为了让机器识别(搜索引擎 – SEO). 而微数据是什么呢?在我看来,微数据也是为了方便机器识别而产生的东西.其有特定的规范,有特定的格式.可以丰富搜索引擎的网页摘要. 先来看看比较官方的解释:HTML5 微数据规范是一种标记内容以描述特定类型的信息,例如评论.人

HTML5新增的form属性简介——张鑫旭

一.引言 HTML5中新增了一个名为form的属性,是一个与处理表单相关的元素. 在HTML4或XHTML中,我们要提交一个表单,必须把相关的控件元素都放在<form>元素下.因为表单提交的时候,会直接忽略不是其子元素的控件.但是,实际情况下,由于页面设计与实现的特殊性,会存在有些表单之外的元素也需要一并提交的情况,这时候,传统的表单功能就显得有些捉襟见肘了. HTML5中新增form属性就是为更好地处理这个问题才出现的.其作用,个人感觉,有点类似于label标签的for属性. 二.更好的实现

span与a元素的键盘聚焦性以及键盘点击性研究——张鑫旭

一.众所周知的与不为所知的 我们平时涉及点击交互事件的时候,都是使用的a元素或者button元素,原因是可以相应键盘focus效果以及回车触发点击事件,这是众所周知的. 但是,可能存在一些特殊情况,我们需要使用默认没有键盘可访问性的元素,例如span元素,我们可以通过一定的设置支持键盘的可访问性,这是不为所知的,也是本文的重点所在. 二.span元素处理与测试 要让一个普通的span元素达到一个含button元素的键盘可访问性,我们需要如下处理: 首先,很显然的,绑定点击事件: 给元素设置tab