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 定义新对象方法
Feb 20 Javascript
多种方式实现JS调用后台方法进行数据交互
Aug 20 Javascript
Javascript日期格式化format函数的使用方法
Aug 30 Javascript
Vue.js实现文章评论和回复评论功能
May 30 Javascript
JS轮播图实现简单代码
Feb 19 Javascript
使用socket.io实现简单聊天室案例
Jan 02 Javascript
vue父组件向子组件传递多个数据的实例
Mar 01 Javascript
jQuery实现鼠标点击处心形漂浮的炫酷效果示例
Apr 12 jQuery
vue-cli脚手架build目录下utils.js工具配置文件详解
Sep 14 Javascript
JavaScript解析JSON数据示例
Jul 16 Javascript
vue 返回上一页,页面样式错乱的解决
Nov 14 Javascript
JavaScript 双向链表操作实例分析【创建、增加、查找、删除等】
Apr 28 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
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
让PHP支持页面回退的两种方法[转]
2007/02/14 PHP
laravel安装zend opcache加速器教程
2015/03/02 PHP
详解php魔术方法(Magic methods)的使用方法
2016/02/14 PHP
php中请求url的五种方法总结
2017/07/13 PHP
Laravel框架下的Contracts契约详解
2020/03/17 PHP
用javascript实现画板的代码
2007/09/05 Javascript
js判断设备是否为PC并调整图片大小
2014/02/12 Javascript
jQuery使用addClass()方法给元素添加多个class样式
2015/03/26 Javascript
C#中使用迭代器处理等待任务
2015/07/13 Javascript
JS实现密码框的显示密码和隐藏密码功能示例
2016/12/26 Javascript
浅谈vue-router 路由传参的方法
2017/12/27 Javascript
AngularJS实现的2048小游戏功能【附源码下载】
2018/01/03 Javascript
微信小程序实现滑动切换自定义页码的方法分析
2018/12/29 Javascript
使用JavaScrip模拟实现仿京东搜索框功能
2019/10/16 Javascript
JavaScript实现简单的图片切换功能(实例代码)
2020/04/10 Javascript
vue双击事件2.0事件监听(点击-双击-鼠标事件)和事件修饰符操作
2020/07/27 Javascript
让python json encode datetime类型
2010/12/28 Python
Python迭代和迭代器详解
2016/11/10 Python
Python实现字典按照value进行排序的方法分析
2017/12/23 Python
TensorFLow用Saver保存和恢复变量
2018/03/10 Python
pandas读取csv文件,分隔符参数sep的实例
2018/12/12 Python
python替换字符串中的子串图文步骤
2019/06/19 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
浅谈CSS3 动画卡顿解决方案
2019/01/02 HTML / CSS
阿拉伯世界最大的电子卖场:Souq埃及
2016/08/01 全球购物
阿玛尼化妆品美国官网:Giorgio Armani Beauty
2017/02/02 全球购物
个性化皮包、小袋、生活配件:Mon Purse
2019/03/26 全球购物
毕业学生推荐信
2013/12/01 职场文书
英语专业自荐书
2014/06/13 职场文书
通知范文怎么写
2015/04/16 职场文书
幼儿园教师个人工作总结2015
2015/05/12 职场文书
2015年学校财务工作总结
2015/05/19 职场文书
民事调解书范文
2015/05/20 职场文书
我的中国梦心得体会范文
2016/01/05 职场文书
python3.9之你应该知道的新特性详解
2021/04/29 Python