0%

JS 封装CSS选择器式的获取元素方法

发布于 / 分类: JavaScript / 暂无评论 / 阅读量 403

最后更新于 2018年12月02日

之前的章节使用都是单一式获取方法,一次只能获得单个或者对应的元素数组,唯一加了获取条件的就是通过class获取元素,我们加了一个用于筛选的idName,当idName存在,class要从这个idName元素下获取,但是这样也不能方便的使用,万一我们要在某个class元素下搜索某个tagName或者class,之前的方法完全不够用了。为此我们衍生出新的获取元素的方法。

我们的希望获取元素可以这样写:

$('#er span i').css('color','red')

获取id为er的元素下的span元素中的i元素,让他的颜色改为红色。

html代码如下:

<p id="er">
    <span id="ps">span</span>
    <span class="td"><i>sad</i>span</span>
    <span>span</span>
</p>

首先我们要对$('#er span i')传入的参数进行调整,传入的是string类型,我们可以通过split()将他转换为数组,但是我们也可能会只传入一个元素,他没有空格这些所以还要做个判断。

//调用Base
var $ = function(args) {
    return new Base(args);
}
//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
     
    }else {

    }
}

从简单的开始我们先判断传入的参数为#er

//调用Base
var $ = function(args) {
    return new Base(args);
}
//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
     
    }else {
         //如果传入的值是文本
        if(typeof args == 'string') { 
           if(args.charAt(0) == '#') {
              this.arr.push(this.getId(args.substring(1)));
           }
        }else if(typeof args == 'object') {
            //因为之前事件绑定时还传过this对象,这里做个兼容
            if(args != undefined) {
                this.arr[0] = args;
            }
        }
    }
}
//获取id元素
Base.prototype.getId = function(id) {
    return document.getElementById(id);
}

通过charAt(0)获取到第一位的值,判断是否为‘#’,如果是的话运行获取id的方法,因为我们现在使用的是$(),在这个方法里面就直接获取到了元素,所以Base.prototype.getId方法也不需要return this了,然后因为id是单个存在的,所以直接返回获取到的对象就行,然后将返回的对象push到数组arr中。

实际上我们传入的参数有三种可能,一种是id,一种是class,一种是tagName,那么每次都 if(args.charAt(0) == 'xxx')来判断有点麻烦,这个if判断要重复写很多次,索性使用switch方法判断。

//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
     
    }else {
         //如果传入的值是文本
        if(typeof args == 'string') { 
          switch(args.charAt(0)) {
              case '#' :
                this.arr.push(this.getId(args.substring(1)));
                break;
            case '.' :
                
                break;
            default :

           }
        }else if(typeof args == 'object') {
            //因为之前事件绑定时还传过this对象,这里做个兼容
            if(args != undefined) {
                this.arr[0] = args;
            }
        }
    }
}

现在判断传入的是class:

//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
     
    }else {
         //如果传入的值是文本
        if(typeof args == 'string') { 
          switch(args.charAt(0)) {
              case '#' :
                this.arr.push(this.getId(args.substring(1)));
                break;
            case '.' :
                this.arr = this.getclass(args.substring(1));
                break;
            default :

           }
        }else if(typeof args == 'object') {
            //因为之前事件绑定时还传过this对象,这里做个兼容
            if(args != undefined) {
                this.arr[0] = args;
            }
        }
    }
}

//获取class元素和id筛选
Base.prototype.getclass = function(className,parentNode) {
    var node = null;
    var temps = [];
    if(parentNode != undefined) {
        node = parentNode;
    }else {
        node = document;
    }
    var elements = node.getElementsByTagName('*');
    for(var i = 0;i<elements.length;i++)  {
        if(elements[i].className.match(className)) {
            temps.push(elements[i]);
        }
    }
    return temps;
}

因为getclass方法return的是数组,所以直接this.arr = 返回的数组就行。

判断传入的是tagName

//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
     
    }else {
         //如果传入的值是文本
        if(typeof args == 'string') { 
          switch(args.charAt(0)) {
              case '#' :
                this.arr.push(this.getId(args.substring(1)));
                break;
            case '.' :
                this.arr = this.getclass(args.substring(1));
                break;
            default :
                this.arr = this.getTagName(args);
           }
        }else if(typeof args == 'object') {
            //因为之前事件绑定时还传过this对象,这里做个兼容
            if(args != undefined) {
                this.arr[0] = args;
            }
        }
    }
}

//通过元素名获取元素
Base.prototype.getTagName = function(tag,parentNode) {
    var node = null;
    var temps = [];
    if(parentNode != undefined) {
        node = parentNode;
    }else {
        node = document;
    }
    var tags = node.getElementsByTagName(tag);
    for(var i = 0;i<tags.length;i++){
        temps.push(tags[i]);
    }
    return temps;
}

getTagName 也是返回的数组,和上面一样this.arr = 返回的数组即可。

下面就是重点了,当传入的参数是复合形式#er span

//基础库
function Base(args) {
    this.arr = [];
    if(args.indexOf(' ') != -1){
         var childNodes = args.split(' ');
        var temNodes = [];
        var node = []; 
        for(var i = 0;i < childNodes.length;i++) {
            if(node.length == 0) node.push(document);
            switch(childNodes[i].charAt(0)) {
                case '#' :
                    temNodes = [];
                    temNodes.push(this.getId(childNodes[i].substring(1)));
                    node = temNodes;
                    break;
                case '.' :
                    temNodes = [];
                    for(var j = 0;j<node.length;j++) {
                        var temps = this.getclass(childNodes[i].substring(1),node[j]);
                        for(var k = 0;k<temps.length;k++){
                            temNodes.push(temps[k])
                        }
                    }
                    node = temNodes;                    
                    break;
                default :
                    temNodes = [];
                    alert(node[0].innerHTML)
                    for(var j = 0;j<node.length;j++) {
                        var temps = this.getTagName(childNodes[i],node[j]);
                        for(var k = 0;k<temps.length;k++){
                            temNodes.push(temps[k])
                        }
                    }            
                    node = temNodes;
            }
        }
        this.arr = temNodes;
    }else {
         //如果传入的值是文本
        if(typeof args == 'string') { 
          switch(args.charAt(0)) {
              case '#' :
                this.arr.push(this.getId(args.substring(1)));
                break;
            case '.' :
                this.arr = this.getclass(args.substring(1));
                break;
            default :
                this.arr = this.getTagName(args);
           }
        }else if(typeof args == 'object') {
            //因为之前事件绑定时还传过this对象,这里做个兼容
            if(args != undefined) {
                this.arr[0] = args;
            }
        }
    }
}

首先创建一个childNodes 变量用来保存args.split(' ')生成的数组,然后再for语句循环这个childNodes里面的值,每个值循环一次,判断是ID,还是class,还是tagName。

如果是ID,那么就运行this.getId(childNodes[i].substring(1)),将搜索的值传入,然后由于是复合式的,我们还要考虑他第二次会有父元素,但是id的方法getElementById只能作用于document,而且id只有一个,所以也没必要传第二个值,但是thia.arr不能通过push的方法传入了,不然你第一次是push,第二次也是push,那你不是都给获取了,根本没有获取范围的效果,所以这里要额外创建一个数组temNodes来临时保存返回的值。

temNodes也是push方法,这样就导致没啥效果啊,和this.arr.push一样,所以在temNodes.push之前要对这个数组重置。temNodes = [];

当for循环完args后,temNodes得到的就是最终的结果,所以我们要将这个结果返回给this.arr,this.arr = temNodes;

当for循环args第二遍时,就会产生父元素用于筛选,id的话可以不用考虑这个父元素,但是如果传入的参数为 #er span,那么span是在#er里面的,我们不可能用temNodes[0]的方式来表示父元素,因为temNodes在返回值之前都会被重置掉,这里我们又要创建一个新的数组node用来保存父元素,所以id在返回完值后也要将这个返回的值传入push中,索性直接就是node = temNodes;

这样每次返回完值后,都要将值传给node,作为下次循环的时候作为父元素存在。

id部分好了,下面为class的时候

也是一样,先重置临时数组temNodes,因为有node的存在,你不知道node里面有多少个值,所以做个for循环,这里的for不能用i了,要用其他的命名,一面和for循环childNodes的i冲突,循环node数组,然后运行this.getclass(childNodes[i].substring(1),node[j]),返回的是一个数组,但是不能直接=temNodes,不然for循环node的时候会无限覆盖,下一个覆盖上一个,这里用一个temps元素保存返回的数组,然后for循环这个数组,依次push到temNodes中去,这样当node数组循环完后,也就得到了所有node元素的下元素了。

得到结果后将结果再传给node,下次循环的时候作为父元素存在。

使用了node就会产生一个问题,如果你是第一次使用的话,你的class又使用了for循环node数组,但是第一次并没有产生node啊,所以在第一次for循环childNodes的时候做个判断,如果没有node表示是第一次,第一次获取都是在document上的,于是if(node.length == 0) node.push(document);

下面就是tagName了

先重置temNodes,然后for循环node数组,和class一样,只是调用的方法为this.getTagName(childNodes[i],node[j]);得到值后再将值传给node。

当for循环childNodes完毕后,表示已经处理完你传入的最后一个参数了,那么将最终的结果返回给arr数组: this.arr = temNodes;

关于获取元素时的第二个参数

在使用getTagName和getclass的时候都要考虑到父元素的存在,所以要传入第二个参数,但是第一次的时候并不会传入第二个参数,所以做个if判断,if(parentNode != undefined)表示parentNode 有值,将node=parentNode ,如果没有就node = document;然后获取的时候从node开始:node.getElementsByTagName('*')....

以上就是封装使用css选择器的方式获取元素了,实际上还有更多的方法,比如>,last-child等等选择器,这些就暂时不弄,等我

html的嵌套错误 JS 浏览器检测
  • 滑动验证
    »
  • weixiao kaixin tushetou jingkong deyi fanu liezui liuhan daku ganga bishi nanguo lihai qian yiwen numu tu yi haixiu se fadai minyan hehe henkaixin huaji biyiyan kuanghan maimeng shui xiaku penqi zhangzui pen aini ye niu laji ok chigua renshi kongbu shuai xiaoxiese touxiao huaixiao jingnu chihuai kaisang xiaoku koubi zhuangbi lianhong kanbujian shafa zhijing xiangjiao dabian yaowan redjing lazhu rizhi duocang chixigua hejiu xixi xiaopen goukun xiaobuchu shenme wusuowei guancha lajing chouyan xiaochi bie zhadanzui zhadanxiao