zoukankan      html  css  js  c++  java
  • 【学】jQuery的源码思路1——后代选择器

    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;
    }
    
  • 相关阅读:
    Linux crontab 命令
    tcpdump抓包工具
    tcpdump过滤某个端口
    ARM处理器基础Cortex-M4
    rtems floating poing switch
    ARM处理器的堆栈和函数调用,以及与Sparc的比较
    关于调用堆栈,任务堆栈
    如何测试嵌入式处理器的CPU使用率
    关于嵌入式实时操作系统的实时性
    RTEMS API
  • 原文地址:https://www.cnblogs.com/bluefantasy728/p/5778003.html
Copyright © 2011-2022 走看看