-
选择器模块之传统做法
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>
//例如给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
/*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>
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; } }
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 ); } }