• 我转过几个弯 绕过那个小雨楼
  • 拿着蒲扇摆着衣衫渡着紧箍咒
  • 不问天涯不停留 喝过几壶酒
  • 不过年少白头道义放胸口
  • 倘若明天之后 遥看前尘剑封侯
  • 似那天上神仙无所求
  • 朝朝暮暮君如梦醒十分不为何理由
  • 是真是假是惶恐是无休
  • 路过这风雨花满楼 片刻都不停留
  • 我本这书生进京赶考留下许多愁
  • 你问有没有时候 我叹这天道默悠悠
  • 能否与我一醉方休
  • 又过了几个弯 算尽天量道莫慌
  • 踏这田园闻这芳草香
  • 跌跌撞撞仗剑天涯折煞不枉无笔良
  • 是梦是幻是温柔是家乡
  • 路过这风雨花满楼 片刻都不停留
  • 我本这书生进京赶考留下许多愁
  • 你问有没有时候 我叹这天道默悠悠
  • 能否与我一醉方休
  • 路过这风雨花满楼 片刻都不停留
  • 我本这书生进京赶考留下许多愁
  • 你问有没有时候 我叹这天道默悠悠
  • 能否与我一醉方休
  • 谁能与我一醉方休

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

101 0

之前的章节使用都是单一式获取方法,一次只能获得单个或者对应的元素数组,唯一加了获取条件的就是通过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等等选择器,这些就暂时不弄,等我

0
  • 本文分类:JavaScript
  • 本文标签:CSS选择器式的获取元素方法
  • 流行热度:已超过 101 人围观了本文
  • 最后更新:2018年12月2日 - 22时45分11秒
  • 发布日期:2018年12月2日 - 22时45分11秒
  • 版权申明:本文系作者@木灵鱼儿原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
微信收款码
微信收款码