大概思路是這樣的:通過判斷傳過來的參數是什么類型,如果是對象,那這里就是this(因為封裝是自己用的,肯定不會隨便亂傳一個對象過來),如果是一個函數(匿名函數),那就是Dom加載(這里先不講),如果是字符串,那就是CSS選擇器,通過判斷是否存在空格,沒有就是單一CSS選擇器,有就是后代選擇器。然后再通過判斷是ID選擇器,類選擇器還是元素選擇器來執行具體的操作:
這里創建一個構造函數實現基礎庫Jr :
function Jr(){ }
在其原型上添加方法:
//獲取ID節點 Jr.prototype.getId = function(id){ return document.getElementById(id); } //獲取CLASS節點數組 Jr.prototype.getClass = function(className, parentNode){ var node = null; //存放父節點 var temps = []; if(parentNode != undefined){ //存在父節點時 node = parentNode; } else { //不存在則默認document node = document; } var all = node.getElementsByTagName('*'); for(var i = 0; i < all.length; i++){ //遍歷所有節點,判斷是否有包含className if((new RegExp('(\\s|^)' + className + '(\\s|$)')).test(all[i].className)){ temps.push(all[i]); } } return temps; } //獲取元素節點數組 Jr.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; }
接下來就是在構造函數里通過傳參來進行一系列選擇器操作:
//基礎庫 function Jr(args){ //創建一個數組,用來保存獲取的節點或節點數組 this.elements = []; //當參數是一個字符串,說明是常規css選擇器,不是this,或者function if(typeof args == 'string'){ //css模擬,就是跟CSS后代選擇器一樣 if(args.indexOf(' ') != -1){ //把節點拆分開並保存在數組里 var elements = args.split(' '); //存放臨時節點對象的數組,解決被覆蓋問題 var childElements = []; var node = []; //用來存放父節點用的 for(var i = 0; i < elements.length; i++){ //如果默認沒有父節點,就指定document if(node.length == 0) node.push(document); switch(elements[i].charAt(0)) { //id case '#' : //先清空臨時節點數組 childElements = []; childElements.push(this.getId(elements[i].substring(1))); node = childElements; //保存到父節點 break; //類 case '.' : childElements = []; //遍歷父節點數組,匹配符合className的所有節點 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'){ if(args != undefined){ this.elements[0] = args; } } else if(typeof args == 'function'){ //這里不講 this.ready(args); } }
最后,我們調用該基礎庫:
//調用 var $ = function(args){ return new Jr(args); }
現在,我們就可以實現如下選擇器等效果了:
$(this) $('#box') $('.box') $('div') $('#box div .nav') $('.box .nav p')
