关于js封装框架类库之选择器引擎(一)

  • 选择器模块之传统做法

        var tag = function (tag){
            return document.getElementsByTagName(tag);
        }
        var id = function (id){
            return document.getElementById(id);
        }
        var className = function (className){
            return document.getElementsByClassName(className);
        }    
  • 由浅入深之tag方法

 这是html部分代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            div, p {
                 200px; 
                height:50px; 
                border:1px dashed red; 
                margin: 10px 0;
            }
        </style>
    </head>
    <body>
        <div></div>
        <div></div>
        <p></p>
        <p></p>
    </body>
View Code
//例如给div盒子添加背景色我们可能会这么做
        var divs = tag('div');
        var each = function (arr){
            for(var i = 0;i< arr.length;i++){
                arr[i].style.backgroundColor = 'pink';
            }
        }
        each(divs);
        //也可能会这么做
        var list = tag('div');
        var each = function (arr,fn){
            for(var i = 0;i<arr.length;i++){
                if(fn.call(arr[i],i,arr[i]) === false ){//等于false时,终止循环
                    break;
                }
            }
        }
        each(list,function(){
            this.style.backgroundColor = 'yellow';
        })
//上式的fn.call(arr[i],i,arr[i]) === false,下面函数也用到这种调用方式,可以做下比较
        var arr = [ 1, 2, 3, 4, 3, 5];
        var each = function ( arr, fn ) {
            for ( var i = 0; i < arr.length; i++ ) {
                if ( fn( i, arr[ i ] ) === false ) {
                    break;
                }
            }
        };
        
        var index = -1;
        each( arr, function ( i, v ) {    
            if ( v === 3 ) {
                index = i;
                return false;//若是break 遍历不会终止 直到遍历完
            }
        } );
        console.log( index );//2
View Code

/*var tag = function (tag){
   return document.getElementsByTagName(tag);
  }*/
  //以上这种写法的缺点是每次获得元素后又要返回,以至于造成浏览器性能的损耗
  //为了简化开发,可以将获得的数组合并到一个数组中,这也是jq中所用到的

var getTag = function ( tag, results ) {
            results = results || [];
            results.push.apply( results, document.getElementsByTagName( tag ) );
            return results;
        };
        var list = getTag('div');
            list = getTag('p',list);//如果再获得p标签,可以这么写
        var each = function (arr,fn){
            for(var i = 0;i<arr.length;i++){
                if(fn.call(arr[i],i,arr[i]) === false ){//等于false时,终止循环
                    break;
                }
            }
        }
        /*each(list,function(){
            this.style.backgroundColor = 'lightgreen';
        })*/
        each(getTag('p',getTag('div')),function(){
            this.style.backgroundColor = 'lightgreen';
        })
  • 进一步整合以上方法 上面方法也只能获得指定标签元素,需求是要兼顾获取标签、id和类名

思路:单独写一个函数,如果再函数中想获得标签、id和类名,直接调用其方法即可

在此用到的html和样式对以下操作的验证

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            div, p {
                 200px; 
                height:50px; 
                border:1px dashed red; 
                margin: 10px 0;
            }
        </style>
    </head>
    <body>
        <div id="id">id</div>
        <div class="class"></div>
        <p></p>
        <p></p>
    </body>
View Code

1、分别列出获取标签、id、类名对应的方法

var getTag = function ( tag, results ) {
            results = results || [];
            results.push.apply( results, document.getElementsByTagName( tag ));
            return results;
        };
        
        var getId = function ( id, results ) {
            results = results || [];
            results.push( document.getElementById( id ) );//此处是单个数据,无须用apply方法
            return results;
        };
        
        var getClass = function ( className, results ) {
            results = results || [];
            results.push.apply( results, document.getElementsByClassName( className ) );
            return results;
        };

2、书写get方法,判断调用以上哪一种方法

var get = function ( selector, results ) {
            results = results || [];
            //                     1          2        3       4
            var rquickExpr = /^(?:#([w-]+)|.([w-]+)|([w]+)|(*))$/,//正则表达式
                m = rquickExpr.exec( selector );//正则匹配
            if ( m ) {//判断是否匹配成功(此处if判断可以省略)
                if ( m[ 1 ] ) {
                    results = getId( m[ 1 ], results );
                } else if ( m[ 2 ] ) {
                    results = getClass( m[ 2 ], results );
                } else if ( m[ 3 ] ) {
                    results = getTag( m[ 3 ], results );
                } else if ( m[ 4 ] ) {
                    results = getTag( m[ 4 ], results );
                }
                
                //因为标签元素选择器和通配符选择器所调用的方法一样,所以可以进行整合如下
                /*if ( m[ 1 ] ) {
                    results = getId( m[ 1 ], results );
                } else if ( m[ 2 ] ) {
                    results = getClass( m[ 2 ], results );
                } else {
                    results = getTag( m[ 3 ] || "*", results )
                }*/
                
            }
            
            return results;//返回results
        };

上面是用正则匹配字符串的,如果不用正则如何实现

var get = function(selector, results) {
        results = results || [];
        if (selector === '*') {
            return results = getTag(selector, results);
        } else {
            var firstChar = selector.charAt(0);
            switch (firstChar) {
                case '.':
                    results = getClass(selector.slice(1), results);
                    break;
                case '#':
                    results = getId(selector.slice(1), results);
                    break;
                default:
                    results = getTag(selector, results);
                    break;
            }
            return results;
        }
    }
View Code

3、书写each方法遍历所获得的元素数组

var each = function ( arr, fn ) {
            for ( var i = 0; i < arr.length; i++ ) {
                if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) {
                    break;
                }
            }
        };

4、调用each方法,执行验证相关需求的操作

each( get( "#id" ), function () {
                
                this.style.backgroundColor = 'lightgreen';    
            } );

最后把以上方法整合在一起,如下

// 注释: 对基本选择器方法的封装
var getTag = function ( tag, results ) {
    results = results || [];
    results.push.apply( results, document.getElementsByTagName( tag ) );
    return results;
};

var getId = function ( id, results ) {
    results = results || [];
    results.push( document.getElementById( id ) );
    return results;
};

var getClass = function ( className, results ) {
    results = results || [];
    
    if ( document.getElementsByClassName ) {
        results.push.apply( results, document.getElementsByClassName( className ) );
    } else {
        each( getTag( '*' ), function ( i, v ) {
            if ( ( ' ' + v.className + ' ' )
                        .indexOf( ' ' + className + ' ' ) != -1 ) {
                results.push( v );
            }
        } );
    }
    return results;
};


// 对each方法循环的封装
var each = function ( arr, fn ) {
    for ( var i = 0; i < arr.length; i++ ) {
        if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) {
            break;
        }
    }
};
        

// 通用的get方法
var get = function ( selector, results ) {
    results = results || [];
    var rquickExpr = /^(?:#([w-]+)|.([w-]+)|([w]+)|(*))$/,
        m = rquickExpr.exec( selector );
    
    if ( m ) {
        
        if ( m[ 1 ] ) {
            results = getId( m[ 1 ], results );
        } else if ( m[ 2 ] ) {
            results = getClass( m[ 2 ], results );
        } else if ( m[ 3 ] ) {
            results = getTag( m[ 3 ], results );
        } else if ( m[ 4 ] ) {
            results = getTag( m[ 4 ], results );
        }
        
    }
View Code

 


以上便是自己的一些学习笔记,鄙人不才,些许浅显,希望大家批评指正

 

原文地址:https://www.cnblogs.com/goweb/p/5373156.html