蓝色幻想728

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

jQuery的源码思路1——后代选择器

这里探讨一下jQuery中后代选择器的封装原理,并自己写一下
getEle('#div1 ul li .box');接受的参数就是个后代选择器,类似于这样:

  • #div1 ul li .box
  • id/tagname/class
  • div#div1
  • div.box
  • input[type=button]
  • li:eq(3)/lt(3)/gt(3)
  • li:first/last/odd/even
function getEle(str){
    var arr = str.match(/\S+/g); //先把传进的字符串用正则匹配一下,把多余的空格去掉再放进数组,知识点:match返回的是一个数组,这里也可以用split,split也可以放正则,但是要用小写's+'
    var aParent = [document]; //一开始以document为父级,但是也要放在数组中
    var aChild = [];
    for(var i=0 ;i<arr.length; i++){//切好后的数组,循环,每次把抓到的数据放到aChild中,再把它赋给下一次循环的父级
        aChild = getByStr(aParent,arr[i]); //需要一个函数,传入父级以及要抓该父级下字符串为第二个参数的元素,抓到的元素赋给数组aChild
        aParent = aChild;//然后将该数组作为下一个循环的父级
    }
    return aChild;
}

function getByStr(aParent,str){
    var aChild = [];
    for (var i=0; i<aParent.length; i++){
        switch (str.charAt(0)){ //判断字符串是否含有#.或者没有,分别代表id,class和标签
            case '#':
                var obj = aParent[i].getElementById(str.substring(1));
                obj && aChild.push(obj);
                break;
            case '.':
                var aEle = getByClass(aParent[i],str.substring(1));
                for(var j=0; j<aEle.length; j++){
                    aChild.push(aEle[j]);
                }
                break;
            default:
                    //div#div1
                if(/\w+#\w+/.test(str)){
                    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]);
                            break; //只抓一个
                        }
                    }
                }else if(/\w+\.\w+/.test(str)){
                    var arr = str.split('.');
                    var aEle = aParent[i].getElementsByTagName(arr[0]);
                    var re = new RegExp('\\b' + arr[1] + '\\b'); //用边界的正则是为了避免出现class中出现多个空格,所以只要找到即可
                    for(var j=0; j<aEle.length; j++){
                        if(re.test(aEle[j].className)){
                            aChild.push(aEle[j]);
                        }
                    }
                }else if(/\w+\[\w+\=\w+]/.test(str)){ //input[type=button]
                    var arr = str.split(/\[|\=|\]/); // ['input','type','button',]
                    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]);
                        }
                    }
                }else if(/\w+\:\w+(\(.\))?/.test(str)){
                    var arr = str.split(/\:|\(|\)/);//[tag,eq,3][tag,first]
                    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 '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++){
                                if(j%2==0){
                                    aChild.push((aEle[j]));
                                }
                            }
                            break;
                        case 'eq':
                            aEle[arr[2]] && aChild.push(aEle[arr[2]]);
                            break;
                        case 'lt':
                            for(var j=0; j<arr[2]; j++){
                                aChild.push(aEle[j]);
                            }
                            break;
                        case 'gt':
                            for(var j=Number(arr[2])+1;j<aEle.length; j++){
                                aChild.push(aEle[j]);
                            }
                            break;
                    }

                }else{
                    var aEle = aParent[i].getElementsByTagName(str);
                    for(var j=0; j<aEle.length; j++)
                    aChild.push(aEle[j]);
                }
        }
    }
    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;
}
posted on 2016-08-16 21:48  蓝色幻想728  阅读(166)  评论(0编辑  收藏  举报