大致的思路已经整理出来,
上一次遍历到的子级是下一次遍历到的父级;
首先开始是对$(str)里面的str字符串进行切片;
var str = ‘ div .abc .edf ‘ $(str); //切片思路如下 //首先在使用选择器时可能手误,前面空了空格,或者后面空了空格;为了增加容错性,在此先对字符串使用trim方法. str = str.replace(/^\s+|\s+$/g,‘‘); console.log(str);//得到‘div .abc .edf‘; //开始对字符串进行切割 var aStr = str.replace(/\s+/g,‘ ‘); console.log(aStr );//得到 ‘div‘,‘.abc‘,‘.edf‘的数组
接着实现获取元素的函数;
思路是让上级遍历的子级变成下次遍历的父级
//获取元素 function getEle(str){ // 切 var arr = str.replace(/^\s+|\s+$/g,"").replace(/\s+/g," ").split(" "); var aParent = [document]; var aChild = []; //循环获取元素 for(var i = 0; i < arr.length; i++){ aChild = getByStr(aParent,arr[i]);//先预定义一个利用字符获取元素的方法 //核心: 上一次子级 是下一次父级 aParent = aChild; } return aChild; }
定义字符获取元素方法;
function getByClass(oParent,sClass){ if(oParent.getElementsByClassName){ return oParent.getElementsByClassName(sClass); } var result = []; var re = new RegExp("\\b"+sClass+"\\b"); var aEle = oParent.getElementsByTagName("*"); for(var i = 0; i < aEle.length; i++){ if( re.test(aEle[i].className) ){ result.push(aEle[i]); } } return result; } function getByStr(aParent,str){ var aChild = []; //选择元素 //str #id .class tagname for(var i = 0; i < aParent.length; i++){ switch(str.charAt(0)){ case "#":// id var obj = document.getElementById(str.substring(1)); aChild.push(obj); break; case ".":// 类 var aEle = getByClass(aParent[i],str.substring(1)); //aChild = aChild.concat(aEle); for(var j = 0; j < aEle.length; j++){ aChild.push(aEle[j]); } break; default://标签 //tagname#id if(/^[a-z0-9]+#[a-z0-9\-_$]+$/i.test(str)){ //[tagname,id] var arr = str.split("#"); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].id == arr[1]){ aChild.push(aEle[j]); } } //li.box } else if(/[a-z0-9]+\.[a-z0-9\-_$]+$/i.test(str)){ // [tagname,class] var arr = str.split("."); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].className == arr[1]){ aChild.push(aEle[j]); } } //input[type=button] } else if(/\w+\[\w+=\w+\]/.test(str)){ //arr [input,type,button,] var arr = str.split(/\[|=|\]/); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].getAttribute(arr[1]) == arr[2]){ aChild.push(aEle[j]); } } //li:first li:eq(index) } else if(/\w+:\w+(\(\.\))?/.test(str)){ /*[li,eq,index,] arr[0] tagname arr[1] first/eq/gt/lt/odd/even arr[2] 内容 */ var arr = str.split(/:|\(|\)/); var aEle = aParent[i].getElementsByTagName(arr[0]); switch(arr[1]){ case "first": aChild.push(aEle[0]); break; case "last": aChild.push(aEle[aEle.length - 1]); break; case "eq": aChild.push(aEle[arr[2]]); break; case "gt"://大于 for(var j = parseInt(arr[2]) + 1; j < aEle.length; j++){ aChild.push(aEle[j]); } break; case "lt"://小于 for(var j = 0; j < parseInt(arr[2]); j++){ aChild.push(aEle[j]); } break; case "odd": for(var j = 0; j < aEle.length; j++){ if(j%2 == 1){ aChild.push(aEle[j]); } } break; case "even": for(var j = 0; j < aEle.length; j+=2){ aChild.push(aEle[j]); } break; } }else {//纯标签 var aEle = aParent[i].getElementsByTagName(str); //aChild = aChild.concat(aEle); for(var j = 0; j < aEle.length; j++){ aChild.push(aEle[j]); } } } } return aChild; }
以上的字符获取元素方法算是比较简单的了。较难的还是一开始的思路定稿。
在此这个选择器也基本完成了,其实直接用sizzle选择器的话会更强大更轻便,但本着生命便是折腾,前端重复造轮子的态度,还是折腾了以上的方法。
全部代码如下
function getByClass(oParent,sClass){ if(oParent.getElementsByClassName){ return oParent.getElementsByClassName(sClass); } var result = []; var re = new RegExp("\\b"+sClass+"\\b"); var aEle = oParent.getElementsByTagName("*"); for(var i = 0; i < aEle.length; i++){ if( re.test(aEle[i].className) ){ result.push(aEle[i]); } } return result; } function getByStr(aParent,str){ var aChild = []; //选择元素 //str #id .class tagname for(var i = 0; i < aParent.length; i++){ switch(str.charAt(0)){ case "#":// id var obj = document.getElementById(str.substring(1)); aChild.push(obj); break; case ".":// 类 var aEle = getByClass(aParent[i],str.substring(1)); //aChild = aChild.concat(aEle); for(var j = 0; j < aEle.length; j++){ aChild.push(aEle[j]); } break; default://标签 //tagname#id if(/^[a-z0-9]+#[a-z0-9\-_$]+$/i.test(str)){ //[tagname,id] var arr = str.split("#"); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].id == arr[1]){ aChild.push(aEle[j]); } } //li.box } else if(/[a-z0-9]+\.[a-z0-9\-_$]+$/i.test(str)){ // [tagname,class] var arr = str.split("."); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].className == arr[1]){ aChild.push(aEle[j]); } } //input[type=button] } else if(/\w+\[\w+=\w+\]/.test(str)){ //arr [input,type,button,] var arr = str.split(/\[|=|\]/); var aEle = aParent[i].getElementsByTagName(arr[0]); for(var j = 0; j < aEle.length; j++){ if(aEle[j].getAttribute(arr[1]) == arr[2]){ aChild.push(aEle[j]); } } //li:first li:eq(index) } else if(/\w+:\w+(\(\.\))?/.test(str)){ /*[li,eq,index,] arr[0] tagname arr[1] first/eq/gt/lt/odd/even arr[2] 内容 */ var arr = str.split(/:|\(|\)/); var aEle = aParent[i].getElementsByTagName(arr[0]); switch(arr[1]){ case "first": aChild.push(aEle[0]); break; case "last": aChild.push(aEle[aEle.length - 1]); break; case "eq": aChild.push(aEle[arr[2]]); break; case "gt"://大于 for(var j = parseInt(arr[2]) + 1; j < aEle.length; j++){ aChild.push(aEle[j]); } break; case "lt"://小于 for(var j = 0; j < parseInt(arr[2]); j++){ aChild.push(aEle[j]); } break; case "odd": for(var j = 0; j < aEle.length; j++){ if(j%2 == 1){ aChild.push(aEle[j]); } } break; case "even": for(var j = 0; j < aEle.length; j+=2){ aChild.push(aEle[j]); } break; } }else {//纯标签 var aEle = aParent[i].getElementsByTagName(str); //aChild = aChild.concat(aEle); for(var j = 0; j < aEle.length; j++){ aChild.push(aEle[j]); } } } } return aChild; } //获取元素 function getEle(str){ // 切 var arr = str.replace(/^\s+|\s+$/g,"").replace(/\s+/g," ").split(" "); var aParent = [document]; var aChild = []; //循环获取元素 for(var i = 0; i < arr.length; i++){ aChild = getByStr(aParent,arr[i]); //核心: 上一次子级 是下一次父级 aParent = aChild; } return aChild; }
时间: 2024-10-06 16:36:41