HTML5-类库系列 通过类名获取标签

2015年03月21日 14:26 0 点赞 0 评论 更新于 2025-11-21 17:58

最近我在给团队讲解 JS 类库的知识,借此机会和大家分享一下类库的搭建过程。我们从简单的核心功能入手,今天要讲解的是如何用原生 JS 实现通过类名获取标签。

在此提醒各位,复杂的功能都是由简单功能逐步优化而来的,所以我们从最简单的功能开始。

第一步:实现基本功能

在我们学过的方法中,可以使用 getElementsByClassName 来获取标签。因此,我们直接用这个方法来实现“通过类名获取标签”的功能。

function getElesByClass(obj, className) {
var result = obj.getElementsByClassName(className);
return result;
}

第二步:发现兼容问题并进行处理

使用上述方法后,我们发现 getElementsByClassName 并不兼容所有浏览器。这时,我们可以采用数组的方法来实现。具体做法是,通过查找标签名(使用“通配符 [*] 选择器”)获取页面中所有的元素,然后将每个元素的类名与我们需要的类名进行比较,把类名相同的元素放入一个数组中,从而实现查找效果。

function getElesByClass(obj, className) {
var result = [];
if (document.getElementsByClassName) {
result = obj.getElementsByClassName(className);
} else {
var eles = document.getElementsByTagName('*');
for (var i = 0; i < eles.length; i++) {
if (eles[i].className == className) {
result.push(eles[i]);
}
}
}
return result;
}

第三步:优化类名

细心的同学可能已经发现,上面的代码存在问题,对于有多个类名的元素无法进行准确比较。所以,在进行类名比较之前,我们需要先对查找到的每个元素进行处理,将每个元素的类名进行切割,利用双 for 循环,将每个元素的每个类名分别和需要的类名进行比较。

function getElesByClass(obj, className) {
var result = [];
if (document.getElementsByClassName) {
result = obj.getElementsByClassName(className);
} else {
var eles = document.getElementsByTagName('*');
var classNameArr = [];
for (var i = 0; i < eles.length; i++) {
// 通过空格分隔开每个类名
classNameArr = eles[i].className.split(" ");
for (var j = 0; j < classNameArr.length; j++) {
if (classNameArr[j] == className) {
result.push(eles[i]);
}
}
}
}
return result;
}

第四步:针对通配符进行优化

我们知道,在编写 CSS 代码时,通常不建议使用通配符,因为通配符的查找速度较慢。在这里,我们也不能随意使用通配符,所以需要进行优化。通过增加一个参数,让程序员可以控制要查找的标签类型,例如查找类名为 .lglp 标签。这种指定标签类型的查找方式比不指定标签类型的查找要快很多。同时,我们也需要考虑程序员不传第三个参数的情况,并进行相应处理。

function getElesByClass(obj, className, targetEle) {
var result = [];
var eles = [];
if (document.getElementsByClassName) {
eles = obj.getElementsByClassName(className);
if (targetEle) {
// 如果有,则需要进行筛选 查找标签名是否一致
var num = 0;
for (var i = 0; i < eles.length; i++) {
if (eles[i].nodeName.toLowerCase() != targetEle) {
continue;
}
result[num] = eles[i];
num++;
}
} else {
result = eles;
}
} else {
if (targetEle) {
eles = obj.getElementsByTagName(targetEle);
} else {
eles = obj.getElementsByTagName('*');
}
var classNameArr = [];
for (var i = 0; i < eles.length; i++) {
// 通过空格分隔开每个类名
classNameArr = eles[i].className.split(" ");
for (var j = 0; j < classNameArr.length; j++) {
if (classNameArr[j] == className) {
result.push(eles[i]);
}
}
}
}
return result;
}

第五步:利用 for-in 循环,简化 for 循环,进行代码优化

function getElesByClass(obj, className, targetEle) {
var result = [], // 存放最终返回值
eles = [], // 存放获取的筛选前的全部标签
classNameArr = []; // 处理复合类名

if (document.getElementsByClassName) {
eles = obj.getElementsByClassName(className);
if (targetEle) {
var num = 0;
for (var i = 0; i < eles.length; i++) {
if (eles[i].nodeName.toLowerCase() != targetEle) {
continue;
}
result[num] = eles[i];
num++;
}
} else {
result = eles;
}
} else {
if (targetEle) {
eles = obj.getElementsByTagName(targetEle);
} else {
eles = obj.getElementsByTagName('*');
}
for (var i = 0; i < eles.length; i++) {
classNameArr = eles[i].className.split(" ");
for (var num in classNameArr) {
if (classNameArr[num] == className) {
result.push(eles[i]);
}
}
}
}
return result;
}

测试用例

以下是一个简单的测试用例,用于验证上述函数的功能。

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>H5course - 刘国利 独行冰海</title>
<link rel="stylesheet" href="../css/reset.css">
<script src="../js/core.js"></script>
</head>
<body>
<p class="test">独行冰海 - 利利</p>
<div id="wrap">
<div class="test con tit">HTML5</div>
<p class="con peo1">独行冰海 - 利利</p>
<p class="con">梦幻雪冰 - 陈能堡</p>
<p class="test">类库构建</p>
</div>
<script>
var wrap = document.getElementById('wrap');
console.log(getElesByClass(wrap, 'con', 'p'));
</script>
</body>
</html>

通过以上步骤,我们逐步实现了通过类名获取标签的功能,并对代码进行了优化和兼容性处理。希望这篇文章能帮助大家更好地理解和掌握相关知识。

作者信息

feifeila

feifeila

共发布了 3994 篇文章