JavaScript通过HTML的class来获取HTML元素的方法总结


Posted in Javascript onMay 24, 2016

对于js来说,我想每一个刚接触它的人都应该会抱怨:为什么没有一个通过class来获取元素的方法。尽管现在高版本的浏览器已经支持getElementsByClassName()函数,但是对于低版本浏览器来说,还是无法兼容,在脱离其他库的时候,还是得自己封装一个方法。

方法一

function getByClass1(parent, cls){
  var res = [];  //存放匹配结果的数组
  var ele = parent.getElementsByTagName('*');
  for(var i = 0; i < ele.length; i++){
    if(ele[i].className == cls){
      res.push(ele[i]);
    }
  }
  return res;
}

当然class里的值只有一个时,上面的方法没问题,但当值为多个时,就会出现问题。

<div class="test"></div>
<div class="test box"></div>
<script>
  getByClass1(document, 'test');  //只获取到第一个div
</script>

方法二

出现问题的时候,我们会尝试着改进,对于多类名的情况我们可以用正则去匹配是否包含所要查找的class名,于是就出现了下面这种写法:

function getByClass2(parent, cls){
  var res = [];
  var reg = new RegExp('\\b' + cls + '\\b', 'i');  //匹配cls是一个独立的单词
  var ele = parent.getElementsByTagName('*');
  for(var i = 0; i < ele.length; i++){
    if(reg.test(ele[i].className)){
      res.push(ele[i]);
    }
  }
  return res;
}

这种方法看似可以,解决了getByClass1()的问题,我也用了好长一段时间,但是还会有一个隐藏的bug。看下面的例子:

<div class="test"></div>
<div class="test_box"></div>
<div class="test-box"></div>
<script>
  getByClass2(document, 'test');  //结果获取到了第一个div和第三个div
</script>

理论上应该只获取到第一个,但是却和我们预期不一样。这个bug源于下面这段代码里的\b

var reg = new RegExp('\\b' + cls + '\\b', 'i');

我们先来看下\b在正则中的表示的意思

\b是正则表达式规定的一个特殊代码,代表着单词的开头或结尾,也就是单词的分界处。

通俗点说:\b就是匹配一个单词(从左边界到右边界)。

而问题也就出在这里,\b把除字母、数字、下划线外的其他字符都当成是边界,对于上面的例子中第三个class值为test-box,\b匹配时,把连字符(-)当作单词边界,所以也匹配了第三个div。

方法三

因此我们还需要对上面方法进行进一步改进,这里参考了stackoverflow上提到的一种方法:

How to Get Element By Class in JavaScript?

改进后的代码如下:

function getByClass3(parent, cls){
  var res = [];
  var reg = new RegExp(' ' + cls + ' ', 'i');  //匹配cls时,两边需要有空格
  var ele = parent.getElementsByTagName('*');
  for(var i = 0; i < ele.length; i++){
    if(reg.test(' ' + ele[i].className + ' ')){
      res.push(ele[i]);
    }
  }
  return res;
}

这种方法舍去了用\b而采用空格来匹配边界,先在获取到的className值两边加上空格,这样就保证了className里的每个值两边都会有空格,然后再用正则去匹配。

用这种方法暂时还未发现问题,但是使用时,方法中的单引号内的空格一定不能落下。

方法四

function getByClass3(parent, cls){
  var res = [];
  var reg = new RegExp('(^|\\s)' + cls + '($|\\s)', 'i');
  var ele = parent.getElementsByTagName('*');
  for(var i = 0; i < ele.length; i++){
    if(reg.test(ele[i].className)){
      res.push(ele[i]);
    }
  }
  return res;
}

空格完全用正则来处理,这样省去了空格容易落下的问题,代码也更美观精简。

那么这种方法是否就是比较完美的呢,其实不然,下面来看下更优的方案。

方法五(完美版)

文章开头已经提到,高版本的浏览器已经支持getElementsByClassName()方法。出于性能考虑,对支持的浏览器使用原生方法势必会更好。而对于低版本的浏览器使用上面的方法四。

function getByClass(parent, cls){
  if(parent.getElementsByClassName){
    return parent.getElementsByClassName(cls);
  }else{
    var res = [];
    var reg = new RegExp(' ' + cls + ' ', 'i')
    var ele = parent.getElementsByTagName('*');
    for(var i = 0; i < ele.length; i++){
      if(reg.test(' ' + ele[i].className + ' ')){
        res.push(ele[i]);
      }
    }
    return res;
  }
}

当然方法五自认为是相对较好的方案,如果有更优秀的方法欢迎留言补充。

Javascript 相关文章推荐
JavaScript 保存数组到Cookie的代码
Apr 14 Javascript
纯js实现背景图片切换效果代码
Nov 14 Javascript
jQuery实现仿Google首页拖动效果的方法
May 04 Javascript
JavaScript实现自动变换表格边框颜色
May 08 Javascript
jqPlot jQuery绘图插件的使用
Jun 18 Javascript
微信小程序  Mustache语法详细介绍
Oct 27 Javascript
selenium 与 chrome 进行qq登录并发邮件操作实例详解
Apr 06 Javascript
Vue的Flux框架之Vuex状态管理器
Jul 30 Javascript
ECMAscript 变量作用域总结概括
Aug 18 Javascript
js实现微信/QQ直接跳转到支付宝APP打开口令领红包功能
Jan 09 Javascript
浅谈Javascript常用正则表达式应用
Mar 08 Javascript
vue组件冲突之引用另一个组件出现组件不显示的问题
Apr 13 Vue.js
jQuery使用中可能被XSS攻击的一些危险环节提醒
May 24 #Javascript
详解Node.js模块间共享数据库连接的方法
May 24 #Javascript
轻松掌握jQuery中wrap()与unwrap()函数的用法
May 24 #Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
May 24 #Javascript
实例解析jQuery中proxy()函数的用法
May 24 #Javascript
jQuery前端开发35个小技巧
May 24 #Javascript
JS+Canvas绘制时钟效果
Aug 20 #Javascript
You might like
ajax 的post方法实例(带循环)
2011/07/04 PHP
XAMPP安装与使用方法详细解析
2013/11/27 PHP
基于PHP实现解密或加密Cloudflar邮箱保护
2020/06/24 PHP
jQuery 学习 几种常用方法
2009/06/11 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
JS实现的页面自定义滚动条效果
2015/10/26 Javascript
JS中的二叉树遍历详解
2016/03/18 Javascript
微信小程序  modal详解及实例代码
2016/11/09 Javascript
Js中async/await的执行顺序详解
2017/09/22 Javascript
vue实现简单loading进度条
2018/06/06 Javascript
Angularjs 根据一个select的值去设置另一个select的值方法
2018/08/13 Javascript
解决Angular2 router.navigate刷新页面的问题
2018/08/31 Javascript
jquery层次选择器的介绍
2019/01/18 jQuery
微信小程序基础教程之worker线程的使用方法
2019/07/15 Javascript
微信小程序自定义tabbar custom-tab-bar 6s出不来解决方案(cover-view不兼容)
2019/11/01 Javascript
python采集博客中上传的QQ截图文件
2014/07/18 Python
在Django的通用视图中处理Context的方法
2015/07/21 Python
详解Django框架中用户的登录和退出的实现
2015/07/23 Python
约瑟夫问题的Python和C++求解方法
2015/08/20 Python
Python win32com 操作Exce的l简单方法(必看)
2017/05/25 Python
Python实现基于TCP UDP协议的IPv4 IPv6模式客户端和服务端功能示例
2018/03/22 Python
python实现根据指定字符截取对应的行的内容方法
2018/10/23 Python
详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据
2020/12/13 Python
Python如何实现单例模式
2016/06/03 面试题
简短的公司员工自我评价分享
2013/11/13 职场文书
付款委托书范本
2014/04/04 职场文书
学生安全责任书
2014/04/15 职场文书
作文评语集锦
2014/12/25 职场文书
个人汇报材料范文
2014/12/30 职场文书
英文商务邀请函范文
2015/01/31 职场文书
2015年世界无烟日活动总结
2015/02/10 职场文书
在职人员跳槽求职信
2015/03/20 职场文书
公务员学习中国梦心得体会
2016/01/05 职场文书
导游词之青岛崂山
2019/12/27 职场文书
Vue+Element UI实现概要小弹窗的全过程
2021/05/30 Vue.js
MySQL系列之七 MySQL存储引擎
2021/07/02 MySQL