深入理解javascript选择器API系列第二篇——getElementsByClassName
前面的话
既然有getElementById()和getElementsByTagName()方法,为什么没有getElementsByClassName()呢?id属性、标签名、class属性并没有什么优劣之分啊。终于,HTML5新增了getElementsByClassName()方法,由于在CSS布局中类名的广泛使用,该方法正好切中痛点,使得通过类名选取元素不再困难,成为最受欢迎的一个方法。接下来,本文将详细介绍该方法
使用
HTML元素的class属性值是一个以空格隔开的列表,可以为空或包含多个标识符。在javascript中class是保留字,所以使用className属性来保存HTML的class属性值
getElementsByClassName()方法接收一个参数,即一个包含一个或多个类名的字符串,返回带有指定类的所有元素的类数组对象HTMLCollection。传入多个类名时,类名的先后顺序不重要。与getElementsByTagName()类似,该方法既可以用于HTML文档对象,也可以用于element元素对象
[注意]IE8-浏览器不支持
<ul id="list">
<li class="a ab c">1</li>
<li class="a">2</li>
<li class="ac">3</li>
<li class="a b c">4</li>
<li class="a b">5</li>
</ul>
<script>
//类名中存在a成立
Array.prototype.forEach.call(list.getElementsByClassName('a'),function(item,index,arr){
item.style.fontWeight = 'bold';
});
//只有类名中同时存在a和c才成立
Array.prototype.forEach.call(list.getElementsByClassName('a c'),function(item,index,arr){
item.style.color = 'red';
});
</script>
classList属性
在操作类名时,需要通过className属性添加、删除和替换类名。因为className是一个字符串,所以即使只修改字符串一部分,也必须每次都设置整个字符串的值。要从className字符串中删除一个类名,需要把类名拆开,删除不想要的那个,再重新拼成一个新字符串
HTML5为所有元素添加了classList属性,这个classList属性是新集合类型DOMTokenList的实例,它有一个表示自己包含多少元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号法
[注意]IE9-浏览器不支持
<div id="test" class="a b c"></div>
<script>
console.log(test.classList);//["a", "b", "c", value: "a b c"]
console.log(test.classList[0]);//a
console.log(test.classList.item(1));//b
</script>
此外,这个新类型还定义如下方法:
add(value) 将给定的字符串值添加到列表中,如果值已存在,则不添加
contains(value) 表示列表中是否存在给定的值,如果存在则返回true,否则返回false
remove(value) 从列表中删除给定的字符串
toggle(value) 如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它
有了classList属性,className属性基本没有什么用武之地了
<style>
.cB{color: blue;}
</style> <body>
<div id="test">测试文字</div>
<button id="btn1" onclick = "test.classList.add('cB')">add</button>
<button id="btn2" onclick = "test.classList.contains('cB')?alert(true):alert(false)">contains</button>
<button id="btn3" onclick = "test.classList.remove('cB')">remove</button>
<button id="btn4" onclick = "test.classList.toggle('cB')">toggle</button>
</body>
扩展
【1】由于原生的getElementsByClassName()方法不兼容IE8-浏览器,且该方法只能完全匹配参数中的类名列表。因此有如下扩展
扩展函数getElementsByClassName(),具有更丰富的功能。如果参数类名列表由空格分隔,则进行且匹配,即只有元素中的类名包含参数类名列表中的所有类名才算匹配成功;如果参数类名列表由逗号分隔,则进行或匹配,即只要元素中的类名包含参数类名列表中的其中一个类型就算匹配成功
Array.prototype.noRepeat = function(){
var result = [];
for(var i = 0; i < this.length; i++){
if(result.indexOf(this[i]) == -1){
result.push(this[i]);
}
}
return result;
}
Array.prototype.inArray = function(value){
for(var i = 0; i < this.length; i++){
if(this[i] === value){
return true;
}
}
return false;
}
function getElementsByClassName(parentObj,classStr){
var result = [];
//获取parentObj下的所有子元素
var objs = parentObj.getElementsByTagName('*');
//条件一:如果classStr用空格分隔,则表示class必须同时满足才有效
var targetArr1 = classStr.trim().split(/\s+/).noRepeat();
//条件二:如果classStr用逗号分隔,则表示class只要有一个满足就有效
var targetArr2 = classStr.trim().split(/\s*,\s*/).noRepeat();
//只有一个class或者进行条件一测试
if(classStr.indexOf(',') == -1 ){
label: for(var i = 0; i < objs.length; i++){
//获取每一个子元素的类名,将其转换为数组后去重
var arr = objs[i].className.trim().split(/\s+/).noRepeat();
//进入循环,测试是否符合条件一
for(var j = 0; j < targetArr1.length; j++){
//如果条件一中的某一项在arr数组中不存在,则跳过该子元素
if(!arr.inArray(targetArr1[j])){
continue label;
}
}
//将符合条件一的子元素对象放在结果数组中
result.push(objs[i]);
}
//返回结果数组
return result;
//进行条件二测试
}else{
label: for(var i = 0; i < objs.length; i++){
//获取每一个子元素的类名,将其转换为数组后去重
var arr =objs[i].className.trim().split(/\s+/).noRepeat();
//进入循环,测试是否符合条件二
for(var j = 0; j < targetArr2.length; j++){
//只要条件二的中某一项在arr数组中存在,就符合
if(arr.inArray(targetArr2[j])){
//将符合条件二的子元素对象放在结果数组中
result.push(objs[i]);
//接着进入下一个子元素测试
continue label;
}
}
}
//返回结果数组
return result;
}
}
<ul id="list">
<li class="a ab c">1</li>
<li class="a">2</li>
<li class="ac">3</li>
<li class="a b c">4</li>
<li class="a b">5</li>
</ul>
<script>
//类名中存在a成立
getElementsByClassName(list,'a').forEach(function(item,index,arr){
item.style.fontWeight = 'bold';
});
//只有类名中同时存在a和c才成立
getElementsByClassName(list,'a c').forEach(function(item,index,arr){
item.style.color = 'red';
});
//只要类名中存在b或c即成立
getElementsByClassName(list,'b,c').forEach(function(item,index,arr){
item.style.backgroundColor = 'pink';
});
</script>
【2】由于IE9-浏览器不支持classList属性,也就不支持add()、contains()、remove()和toggle()这四个方法,下面是这四个方法的兼容写法
由于indexOf()和trim()方法都是ES5新增方法,在低版本IE浏览器中不支持,所以需要重新封装
//数组的indexOf方法封装
function indexOf(arr,value,start){
//如果不设置start,则默认start为0
if(arguments.length == 2){
start = 0;
}
//如果数组中存在indexOf方法,则用原生的indexOf方法
if(arr.indexOf){
return arr.indexOf(value,start);
}
for(var i = start; i < arr.length; i++){
if(arr[i] === value){
return i;
}
}
return -1;
}
//数组去重方法封装
function noRepeat(arr){
var result = [];
for( var i = 0; i < arr.length; i++){
if(indexOf(result,arr[i]) == -1){
result.push(arr[i]);
}
}
return result;
}
//inArray方法封装
function inArray(arr,value){
for(var i = 0; i < arr.length; i++){
if(arr[i] === value){
return true;
}
}
return false;
}
//去除首尾空格函数封装
function trim(arr){
var result = arr.replace(/^\s+|\s+$/g,'');
return result;
}
1、add函数封装
function addClass(obj,classStr){
var array = noRepeat(trim(obj.className).split('\s+'));
if(!inArray(array,classStr)){
array.push(classStr);
}
obj.className = array.join(' ');
return obj;
}
2、contains函数封装
function containsClass(obj,classStr){
var array = noRepeat(trim(obj.className).split('\s+'));
if(inArray(array,classStr)){
return true;
}
return false;
}
3、remove函数封装
function removeClass(obj,classStr){
var array = noRepeat(trim(obj.className).split('\s+'));
var index = indexOf(array,classStr);
if(index != -1){
array.splice(index,1);
obj.className = array.join(' ');
}
return obj;
}
4、toggle函数封装
function toggleClass(obj,classStr){
var array = noRepeat(trim(obj.className).split('\s+'));
if(inArray(array,classStr)){
removeClass(obj,classStr);
}else{
addClass(obj,classStr);
}
}
<style>
.cB{color: blue;}
</style> <div id="test">测试文字</div>
<button id="btn1" onclick = "addClass(test,'cB')">add</button>
<button id="btn2" onclick = "containsClass(test,'cB')?alert(true):alert(false)">contains</button>
<button id="btn3" onclick = "removeClass(test,'cB')">remove</button>
<button id="btn4" onclick = "toggleClass(test,'cB')">toggle</button>
深入理解javascript选择器API系列第二篇——getElementsByClassName的更多相关文章
- 深入理解javascript选择器API系列第一篇——4种元素选择器
× 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...
- 深入理解javascript选择器API系列第三篇——h5新增的3种selector方法
× 目录 [1]方法 [2]非实时 [3]缺陷 前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuer ...
- 深入理解javascript选择器API系列第三篇——HTML5新增的3种selector方法
前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuery的称赞,很多是由于jQuery方便的元素选择器 ...
- 深入理解javascript函数进阶系列第二篇——函数柯里化
前面的话 函数柯里化currying的概念最早由俄国数学家Moses Schönfinkel发明,而后由著名的数理逻辑学家Haskell Curry将其丰富和发展,currying由此得名.本文将详细 ...
- 深入理解javascript函数进阶系列第一篇——高阶函数
前面的话 前面的函数系列中介绍了函数的基础用法.从本文开始,将介绍javascript函数进阶系列,本文将详细介绍高阶函数 定义 高阶函数(higher-order function)指操作函数的函数 ...
- 深入理解脚本化CSS系列第二篇——查询计算样式
× 目录 [1]getComputedStyle [2]注意事项 [3]currentStyle[4]IE 前面的话 元素的渲染结果是多个CSS样式博弈后的最终结果,这也是CSS中的C(cascade ...
- 深入理解DOM事件类型系列第二篇——键盘事件
× 目录 [1]类型 [2]顺序 [3]按键信息[4]应用 前面的话 鼠标和键盘是电脑端主要的输入设备,上篇介绍了鼠标事件,本文将详细介绍键盘事件 类型 键盘事件用来描述键盘行为,主要有keydown ...
- 深入理解DOM事件机制系列第二篇——事件处理程序
× 目录 [1]HTML [2]DOM0级 [3]DOM2级[4]IE[5]总结 前面的话 事件处理程序又叫事件侦听器,实际上就是事件的绑定函数.事件发生时会执行函数中相应代码.事件处理程序有HTML ...
- 深入理解javascript函数系列第二篇——函数参数
× 目录 [1]arguments [2]内部属性 [3]函数重载[4]参数传递 前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传 ...
随机推荐
- linux的top命令参数详解
简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...
- win7,Mindmanager2012使用模板时弹出Runtime error R6025解决方法
Mindjet.MindManager2012.v10.0在应用个别模板时提示"参数错误",然后自动关闭. 解决办法: 如果是win7系统,可以进入C:\Users\(用户名)\A ...
- embedding mono实战笔录(一)
最近在给自己的服务器节点添加脚本功能,考虑到 执行性能.开发效率.调试效率.可维护性.严谨性 五大要素,最终选用C#作为脚本语言,并使用mono作为中间层,使其具备跨平台特性,以备具有在Windows ...
- 《深入理解Java虚拟机》类文件结构
上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...
- 如何安装一个优秀的BUG管理平台——真的是手把手教学!
前言 就BUG管理而言,国内的禅道做得很不错,而且持续有更新.我们来看看如何从头到尾安装禅道,各位要注意的是,不是文章深或者浅,而是文章如何在遇到问题的时候,从什么途径和用什么方法解决问题的.现在发觉 ...
- ASP.NET MVC 视图(一)
ASP.NET MVC 视图(一) 前言 从本篇开始就进入到了MVC中的视图部分,在前面的一些篇幅中或多或少的对视图和视图中的一些对象的运用进行了描述,不过毕竟不是视图篇幅说的不全面,本篇首先为大家讲 ...
- fir.im Weekly - APP 性能监测优化 二三事
每一个成功的 App,都拥有强大的性能体验.本期 fir.im Weekly 整理了微信读书.美团外卖. 天猫.美团点评技术团队的关于性能监测优化方面策略和工具的分享,一起来看看. 微信读书 iOS ...
- PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式
SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分.原文解释是这样的“The Standard PHP Library (SPL) is a col ...
- Web中的XHRHttpRequest
1.提出者:Jesse James Garrett 2.IE中,XHR是通过ActiveX对象实现的.涉及浏览器的兼容性写法. 3.使用 <1>open("请求方式&qu ...
- Android okHttp网络请求之Json解析
前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...