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 相关文章推荐
js下写一个事件队列操作函数
Jul 19 Javascript
简单学习JavaScript中的for语句循环结构
Nov 10 Javascript
Angularjs整合微信UI(weui)
Mar 15 Javascript
jQuery实现查找链接文字替换属性的方法
Jun 27 Javascript
Bootstrap在线电子商务网站实战项目5
Oct 14 Javascript
原生js实现网页顶部自动下拉/收缩广告效果
Jan 20 Javascript
jQuery插件jqGrid动态获取列和列字段的方法
Mar 03 Javascript
js 中rewrap-ajax.js插件实例代码
Oct 20 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
Dec 15 Javascript
使用weixin-java-miniapp配置进行单个小程序的配置详解
Mar 29 Javascript
vuex 中插件的编写案例解析
Jun 10 Javascript
如何从头实现一个node.js的koa框架
Jun 17 Javascript
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
mysql5详细安装教程
2007/01/15 PHP
用Json实现PHP与JavaScript间数据交换的方法详解
2013/06/20 PHP
php常用数学函数汇总
2014/11/21 PHP
php表单习惯用的正则表达式
2017/10/11 PHP
asp函数split()对应php函数explode()
2019/02/27 PHP
js压缩工具 yuicompressor 使用教程
2010/03/31 Javascript
基于jquery的返回顶部效果(兼容IE6)
2011/01/17 Javascript
javascript几个易错点记录
2014/11/26 Javascript
jQuery实现菜单感应鼠标滑动动画效果的方法
2015/02/28 Javascript
通过隐藏iframe实现无刷新上传文件操作
2016/03/16 Javascript
超漂亮的Bootstrap 富文本编辑器summernote
2016/04/05 Javascript
AngularJS基于ngInfiniteScroll实现下拉滚动加载的方法
2016/12/14 Javascript
详解vue slot插槽的使用方法
2017/06/13 Javascript
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
js原生方法被覆盖,从新赋值原生的方法
2018/01/02 Javascript
深入浅析angular和vue还有jquery的区别
2018/08/13 jQuery
[36:19]2018DOTA2亚洲邀请赛 小组赛 A组加赛 Newbee vs LGD
2018/04/03 DOTA
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
python 开发的三种运行模式详细介绍
2017/01/18 Python
详解python中的装饰器
2018/07/10 Python
python使用matplotlib库生成随机漫步图
2018/08/27 Python
Python  unittest单元测试框架的使用
2018/09/08 Python
Django接收自定义http header过程详解
2019/08/23 Python
使用python-Jenkins批量创建及修改jobs操作
2020/05/12 Python
2021年值得向Python开发者推荐的VS Code扩展插件
2021/01/25 Python
CSS3中background-clip和background-origin的区别示例介绍
2014/03/10 HTML / CSS
英国创新设计文具、卡片和礼品包装网站:Paperchase
2018/07/14 全球购物
德国药房apodiscounter中文官网:德国排名前三的网上药店
2019/06/03 全球购物
实习鉴定范文
2013/12/19 职场文书
运动会开幕式邀请函
2014/01/22 职场文书
事业单位个人查摆问题及整改措施
2014/10/28 职场文书
优秀班主任工作总结2015
2015/05/25 职场文书
学生会招新宣传语
2015/07/13 职场文书
2019年怎样写好导游词?
2019/07/02 职场文书
Python pandas读取CSV文件的注意事项(适合新手)
2021/06/20 Python
利用Redis实现点赞功能的示例代码
2022/06/28 Redis