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 相关文章推荐
jquery提升性能最佳实践小结
Dec 06 Javascript
仅IE9/10同时支持script元素的onload和onreadystatechange事件分析
Apr 27 Javascript
js实时获取系统当前时间实例代码
Jun 28 Javascript
javascript弹出层输入框(示例代码)
Dec 11 Javascript
form表单action提交的js部分与html部分
Jan 07 Javascript
原生js和jQuery随意改变div属性style的名称和值
Oct 22 Javascript
JavaScript实现同一页面内两个表单互相传值的方法
Aug 12 Javascript
js与jquery正则验证电子邮箱、手机号、邮政编码的方法
Jul 04 Javascript
Backbone View 之间通信的三种方式
Aug 09 Javascript
js浏览器html5表单验证
Oct 17 Javascript
Node与Python 双向通信的实现代码
Jul 16 Javascript
详解Vue router路由
Nov 20 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
PHP4.04简明安装
2006/10/09 PHP
在PHP中执行系统外部命令
2006/10/09 PHP
nginx+php-fpm配置文件的组织结构介绍
2012/11/07 PHP
php PDO实现的事务回滚示例
2017/03/23 PHP
Thinkphp5行为使用方法汇总
2017/12/21 PHP
PHP实现基于PDO扩展连接PostgreSQL对象关系数据库示例
2018/03/31 PHP
node.js中debug模块的简单介绍与使用
2017/04/25 Javascript
Vue2.x中的父组件传递数据至子组件的方法
2017/05/01 Javascript
使用Node.js实现ORM的一种思路详解(图文)
2017/10/24 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
Vue项目部署的实现(阿里云+Nginx代理+PM2)
2019/03/26 Javascript
M2实现Nodejs项目自动部署的方法步骤
2019/05/05 NodeJs
解决Vue.js应用回退或刷新界面时提示用户保存修改问题
2019/11/24 Javascript
JS实现简单打字测试
2020/06/24 Javascript
[01:20]PWL开团时刻DAY9——听说潮汐没用?
2020/11/10 DOTA
跟老齐学Python之有容乃大的list(4)
2014/09/28 Python
python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
2017/03/12 Python
python+django+sql学生信息管理后台开发
2018/01/11 Python
python中的内置函数max()和min()及mas()函数的高级用法
2018/03/29 Python
用Python将结果保存为xlsx的方法
2019/01/28 Python
从pandas一个单元格的字符串中提取字符串方式
2019/12/17 Python
Python函数参数定义及传递方式解析
2020/06/10 Python
如何用 Python 处理不平衡数据集
2021/01/04 Python
35款精致的 CSS3 和 HTML5 网页模板 推荐
2012/08/03 HTML / CSS
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
如何通过 CSS 写出火焰效果
2021/03/24 HTML / CSS
资深财务管理人员自我评价
2013/09/22 职场文书
商务英语专业应届毕业生求职信
2013/10/28 职场文书
生物专业个人自荐信范文
2013/11/29 职场文书
装饰资料员岗位职责
2013/12/30 职场文书
2014年小学数学教师工作总结
2014/12/03 职场文书
毕业生求职自荐信(2016最新版)
2016/01/28 职场文书
Windows环境下实现批量执行Sql文件
2021/10/05 SQL Server
使用opencv-python如何打开USB或者笔记本前置摄像头
2022/06/21 Python