使用原生JavaScript實現jQuery的css選擇器
阿新 • • 發佈:2018-12-26
使用原生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);
};