最近在给自己的团队讲解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代码时,通常不允许使用通配符,原因在于通配符的查找速度有一定的问题。在这里我们也不能随意使用通配符,因此我们此处需要进行优化,通过增加一个参数,让程序员控制要查找的标签类型,如查找类名为.lgl的p标签。这样的查找,要比不指定标签类型的查找,快很多。另外,我们也必须考虑到程序员不传第三个参数的可能性,并进行相关处理。
- 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>
结束~!