1. 程式人生 > >使用原生JavaScript實現jQuery的css選擇器

使用原生JavaScript實現jQuery的css選擇器

使用原生JS實現jQuery的css選擇器,考慮以下幾個問題:

1.jQuery用$符號傳參的形式獲取節點的物件:1)傳參有可能是字串;2)有可能是一個節點物件;3)有可能直接是一個函式,就是$(function(){}),這個形式。所以需要分三種情況

2.字串又分以下幾種情況:1)包含層層遞進的css選擇器,例如$('#a .b p'),中間會出現空格;2)只有一個字串
3.不管是層層遞進的後代選擇器還是簡單選擇的情況,具體選擇時每一個字串可能是ID選擇,類選擇,或者普通選擇
function Base(args){		//定義一個建構函式,引數為args
	this.elements=[];		//定義一個存放查詢到的節點物件或者物件集合
	
	if(typeof args=='string'){//判斷傳遞的引數是那種情況,字串或者物件節點或者函式
		
if(args.indexOf(' ') !=-1){//判斷字串的時候是否有空格
			var elements=args.split(' ');//將字串用空格分割成陣列,並儲存在elements變數裡面
			var childElements=[];//定義一個子陣列,存放當前查詢的節點,最後結果賦值給物件的elements陣列
			var node=[]; 
			for(var i=0;i<elements.length;i++){//遍歷elements陣列,判斷每個陣列值得第一個字元
				if(node.length==0) node=document;//每次查詢的n.getElementById()中n為當前查詢到的節點
				switch(elements[i].charAt(0)){
					case '#':
						childElements=[];	
						childElements.push(this.getId(elements[i].substring(1)));
						node=childElements;		
						break;		
					case '.':
						childElements=[];		//下一次迴圈時先將之前的大範圍清空,準備放小範圍
						for(var j=0;j<node.length;j++){
							var temps=this.getClass(elements[i].substring(1),node[j]);
							for(var k=0;k<temps.length;k++){
								childElements.push(temps[k]);
							}
						}
						node=childElements;		//將本次得到的節點作為父節點儲存起來
						break;
					default:
						childElements=[];		
						for(var j=0;j<node.length;j++){
							var temps=this.getTagName(elements[i],node[j]);
							for(var k=0;k<temps.length;k++){
								childElements.push(temps[k]);
							}
						}
						node=childElements;					
				}
			}
			this.elements=childElements;	//將最後得到的小範圍陣列賦值給原型陣列準備後續的操作
		}else{
			//find查詢節點
			switch(args.charAt(0)){
				case '#':
					this.elements.push(this.getId(args.substring(1)));		//不一定得到一個,所以直接放進陣列,不用放到數組裡面的第一個
					break;		//直傳一個引數,所以判斷出時直接跳出迴圈
				case '.':
					this.elements=this.getClass(args.substring(1));	
					break;
				default:
					this.elements=this.getTagName(args);
			}
		}
	}else if(typeof args=='object'){		//undefiend和物件都返回object
		if(typeof args!='undefined'){
				this.elements[0]=args;
		}
	}else if(typeof args=='function'){
		this.ready(args);
	}
			
};
//工具函式,給原型物件中新增方法
Base.prototype.getId=function(id){
return document.getElementById(id);
}
Base.prototype.getClass=function(className,parentNode){
var node=null;
var temps=[];
if(parentNode!=undefined){
node=parentNode;
}else{
node=document;
}

var all=node.getElementsByTagName('*');//通過標籤*獲取全部節點
for(var i=0;i<all.length;i++){
if((new RegExp('(\\s|^)' +className +'(\\s|$)')).test(all[i].className)){
temps.push(all[i]);
}
}
return temps;
}
Base.prototype.getTagName=function(tag,parentNode){
var node=null;
var temps=[];
if(parentNode!=undefined){
node=parentNode;
}else{
node=document;
}
var tags=node.getElementsByTagName(tag);
for(var i=0;i<tags.length;i++){
temps.push(tags[i]);
}

return temps;

}
Base.prototype.ready=function(args){
	//DOM載入
}
//通過$呼叫
var $=function(args){
return new Base(args);
};