实现一个类似jquery选择器的小轮子(二)

  大致的思路已经整理出来,

  上一次遍历到的子级是下一次遍历到的父级;

首先开始是对$(str)里面的str字符串进行切片;

var str = '  div .abc .edf   '
$(str);
//切片思路如下
//首先在使用选择器时可能手误,前面空了空格,或者后面空了空格;为了增加容错性,在此先对字符串使用trim方法.
str = str.replace(/^\s+|\s+$/g,'');
console.log(str);//得到'div .abc .edf';
//开始对字符串进行切割
var aStr = str.replace(/\s+/g,' ');
console.log(aStr );//得到 'div','.abc','.edf'的数组

 

接着实现获取元素的函数;

思路是让上级遍历的子级变成下次遍历的父级

//获取元素
function getEle(str){
    //
    var arr = str.replace(/^\s+|\s+$/g,"").replace(/\s+/g," ").split(" ");
    var aParent = [document];
    var aChild  = [];
    
    //循环获取元素
    for(var i = 0; i < arr.length; i++){

        aChild = getByStr(aParent,arr[i]);//先预定义一个利用字符获取元素的方法
        
        //核心: 上一次子级 是下一次父级
        aParent = aChild;
    }
     
    return aChild;
}

定义字符获取元素方法;

function getByClass(oParent,sClass){
    
    if(oParent.getElementsByClassName){
        return oParent.getElementsByClassName(sClass);
    }
    
    var result = [];
    var re = new RegExp("\\b"+sClass+"\\b");
    
    var aEle = oParent.getElementsByTagName("*");
    
    for(var i = 0; i < aEle.length; i++){
        if( re.test(aEle[i].className) ){
            result.push(aEle[i]);
        }
    }
    return result;
}
function getByStr(aParent,str){
    var aChild = [];
    
    //选择元素
    //str  #id  .class  tagname
    for(var i = 0; i < aParent.length; i++){
        switch(str.charAt(0)){
            case "#":// id
                var obj = document.getElementById(str.substring(1));
                aChild.push(obj);
                break;
            case "."://
                var aEle = getByClass(aParent[i],str.substring(1));
                //aChild = aChild.concat(aEle);
                for(var j = 0; j < aEle.length; j++){
                    aChild.push(aEle[j]);
                }
                break;
            default://标签
            
                //tagname#id 
                if(/^[a-z0-9]+#[a-z0-9\-_$]+$/i.test(str)){
                    //[tagname,id]
                    var arr = str.split("#");
                    var aEle = aParent[i].getElementsByTagName(arr[0]);
                    for(var j = 0; j < aEle.length; j++){
                        if(aEle[j].id == arr[1]){
                            aChild.push(aEle[j]);
                        }
                    }
                //li.box
                } else if(/[a-z0-9]+\.[a-z0-9\-_$]+$/i.test(str)){
                     // [tagname,class]
                     var arr = str.split(".");
                     var aEle = aParent[i].getElementsByTagName(arr[0]);
                    for(var j = 0; j < aEle.length; j++){
                        if(aEle[j].className == arr[1]){
                            aChild.push(aEle[j]);
                        }
                    }
                //input[type=button] 
                } else if(/\w+\[\w+=\w+\]/.test(str)){
                    
                    //arr [input,type,button,]
                    var arr = str.split(/\[|=|\]/);
                    var aEle = aParent[i].getElementsByTagName(arr[0]); 
                    for(var j = 0; j < aEle.length; j++){
                    
                        if(aEle[j].getAttribute(arr[1])  == arr[2]){
                            aChild.push(aEle[j]);
                        }
                    }
                    //li:first  li:eq(index) 
                } else if(/\w+:\w+(\(\.\))?/.test(str)){
                    
                    /*[li,eq,index,]
                      arr[0]  tagname
                      arr[1]  first/eq/gt/lt/odd/even
                      arr[2]  内容
                    */
                    var arr = str.split(/:|\(|\)/);
                    var aEle = aParent[i].getElementsByTagName(arr[0]);                    
                    switch(arr[1]){
                        case "first":
                            aChild.push(aEle[0]);
                            break;
                        case "last":
                           aChild.push(aEle[aEle.length - 1]);
                            break;
                        case "eq":
                            aChild.push(aEle[arr[2]]);
                            break;
                        case "gt"://大于
                            for(var j = parseInt(arr[2]) + 1; j < aEle.length; j++){
                                aChild.push(aEle[j]);
                                
                            }
                        
                        break;
                        case "lt"://小于
                            for(var j = 0; j < parseInt(arr[2]); j++){
                                aChild.push(aEle[j]);
                                
                            }
                            break;
                        case "odd":
                            for(var j = 0; j < aEle.length; j++){
                                if(j%2 == 1){
                                    aChild.push(aEle[j]);
                                }                                
                            }
                        break;
                        case "even":
                            for(var j = 0; j < aEle.length; j+=2){
                                aChild.push(aEle[j]);                                
                            }
                        break;
                    }
                    
                    
                    
                }else {//纯标签
                    var aEle = aParent[i].getElementsByTagName(str);
                    //aChild = aChild.concat(aEle);
                    for(var j = 0; j < aEle.length; j++){
                        aChild.push(aEle[j]);
                    }
                }
        }
        
    }
    return aChild;
}

以上的字符获取元素方法算是比较简单的了。较难的还是一开始的思路定稿。

在此这个选择器也基本完成了,其实直接用sizzle选择器的话会更强大更轻便,但本着生命便是折腾,前端重复造轮子的态度,还是折腾了以上的方法。

全部代码如下

function getByClass(oParent,sClass){
    
    if(oParent.getElementsByClassName){
        return oParent.getElementsByClassName(sClass);
    }
    
    var result = [];
    var re = new RegExp("\\b"+sClass+"\\b");
    
    var aEle = oParent.getElementsByTagName("*");
    
    for(var i = 0; i < aEle.length; i++){
        if( re.test(aEle[i].className) ){
            result.push(aEle[i]);
        }
    }
    return result;
}


function getByStr(aParent,str){
    var aChild = [];
    
    //选择元素
    //str  #id  .class  tagname
    for(var i = 0; i < aParent.length; i++){
        switch(str.charAt(0)){
            case "#":// id
                var obj = document.getElementById(str.substring(1));
                aChild.push(obj);
                break;
            case "."://
                var aEle = getByClass(aParent[i],str.substring(1));
                //aChild = aChild.concat(aEle);
                for(var j = 0; j < aEle.length; j++){
                    aChild.push(aEle[j]);
                }
                break;
            default://标签
            
                //tagname#id 
                if(/^[a-z0-9]+#[a-z0-9\-_$]+$/i.test(str)){
                    //[tagname,id]
                    var arr = str.split("#");
                    var aEle = aParent[i].getElementsByTagName(arr[0]);
                    for(var j = 0; j < aEle.length; j++){
                        if(aEle[j].id == arr[1]){
                            aChild.push(aEle[j]);
                        }
                    }
                //li.box
                } else if(/[a-z0-9]+\.[a-z0-9\-_$]+$/i.test(str)){
                     // [tagname,class]
                     var arr = str.split(".");
                     var aEle = aParent[i].getElementsByTagName(arr[0]);
                    for(var j = 0; j < aEle.length; j++){
                        if(aEle[j].className == arr[1]){
                            aChild.push(aEle[j]);
                        }
                    }
                //input[type=button] 
                } else if(/\w+\[\w+=\w+\]/.test(str)){
                    
                    //arr [input,type,button,]
                    var arr = str.split(/\[|=|\]/);
                    var aEle = aParent[i].getElementsByTagName(arr[0]); 
                    for(var j = 0; j < aEle.length; j++){
                    
                        if(aEle[j].getAttribute(arr[1])  == arr[2]){
                            aChild.push(aEle[j]);
                        }
                    }
                    //li:first  li:eq(index) 
                } else if(/\w+:\w+(\(\.\))?/.test(str)){
                    
                    /*[li,eq,index,]
                      arr[0]  tagname
                      arr[1]  first/eq/gt/lt/odd/even
                      arr[2]  内容
                    */
                    var arr = str.split(/:|\(|\)/);
                    var aEle = aParent[i].getElementsByTagName(arr[0]);                    
                    switch(arr[1]){
                        case "first":
                            aChild.push(aEle[0]);
                            break;
                        case "last":
                           aChild.push(aEle[aEle.length - 1]);
                            break;
                        case "eq":
                            aChild.push(aEle[arr[2]]);
                            break;
                        case "gt"://大于
                            for(var j = parseInt(arr[2]) + 1; j < aEle.length; j++){
                                aChild.push(aEle[j]);
                                
                            }
                        
                        break;
                        case "lt"://小于
                            for(var j = 0; j < parseInt(arr[2]); j++){
                                aChild.push(aEle[j]);
                                
                            }
                            break;
                        case "odd":
                            for(var j = 0; j < aEle.length; j++){
                                if(j%2 == 1){
                                    aChild.push(aEle[j]);
                                }                                
                            }
                        break;
                        case "even":
                            for(var j = 0; j < aEle.length; j+=2){
                                aChild.push(aEle[j]);                                
                            }
                        break;
                    }
                    
                    
                    
                }else {//纯标签
                    var aEle = aParent[i].getElementsByTagName(str);
                    //aChild = aChild.concat(aEle);
                    for(var j = 0; j < aEle.length; j++){
                        aChild.push(aEle[j]);
                    }
                }
        }
        
    }
    return aChild;
}


//获取元素
function getEle(str){
    //
    var arr = str.replace(/^\s+|\s+$/g,"").replace(/\s+/g," ").split(" ");
    var aParent = [document];
    var aChild  = [];
    
    //循环获取元素
    for(var i = 0; i < arr.length; i++){

        aChild = getByStr(aParent,arr[i]);
        
        //核心: 上一次子级 是下一次父级
        aParent = aChild;
    }
     
    return aChild;
}
View Code

 

posted @ 2015-09-07 21:51  vidyWu  阅读(180)  评论(0编辑  收藏  举报