在上一篇文章中,我们封装了指定元素下的getId(selector,parent)和getTags(selector,parent)方法,接下来,我们封装类的处理,首先代码供大家参考:
//封装类(兼容处理) function getClasses(className, parent) { var result = []; parent = parent || document; if (support.getElementsByClassName === true) { result.push.apply(result, parent.getElementsByClassName(className)); } else { //1、获取所有元素:document.getElementsByTagName("*") var tags = getTags("*", parent); //2、遍历元素 for (var i = 0, len = tags.length; i < len; i++) { //2.1、获取每个元素的className(也就是元素的class属性) var tagClassName = tags[i].className;//"content c2 c3" if (tagClassName) { //加空格的目的:1、查找字符串"content2"的"content" //2、查找字符串"content c2 c3"的"c3" var changeName = " " + tagClassName + " ";//" content c1 c2 " var chageParam = " " + className + " ";//" content " if (changeName.indexOf(chageParam) >= 0) {//if在具有class属性的元素中找到了 result.push(tags[i]); } } } } return result; };//封装类结束
代码中也给大家作出了详细注释,getClasses(selector,parent)方法变化并不大,只是在得到所有标签的时候使用了:
//1、获取所有元素:document.getElementsByTagName("*") var tags = getTags("*", parent);
这里应该也很容易理解,所以到此为止,我们选择器基本上已经有了雏形,有的人会觉得这样封装需要一个一个调用,会显得很麻烦,接下来,我们继续完善$get()方法,这里的代码仅供大家参考:
//统一封装的调用 function $get(selector,parent){ //接收返回值 var result=[]; //以下判断选parent类型(选择器,dom元素,dom数组三种类型); if (typeof selector === "string"){//判断选择器是否是字符串 //如果是选择器的话 //使用正则表达式,检测字符串, var reg = /^(#([a-zA-Z_]\w*)|[.]([a-zA-Z_]\w*)|([a-zA-Z][a-zA-Z0-9]*|[*]))$/; var regResult=reg.exec(selector);//返回的是一个数组 //如果匹配到 if(regResult){ parent=parent || document; var namef;//用一个变量保存查找数组指定索引的元素,减少查找次数 //判断数组的元素是否有值,id:索引伪2 class:索引为3 标签:索引为4 if (typeof parent === "string"){//判断parent parent=$get(parent); }else if (parent.nodeType){//判断parent是不是一个Dom元素(dom元素都有节点) parent=[parent]; } //都不符合条件的话,parent就是一个dom数组 //使用循环遍历 for(var i=0;i<parent.length;i++){ var evrParent=parent[i]; var singleResult;//变量保存值 if(name=regResult[2]){//所要查找选择器返回的字符串是id的时候 singleResult=getId(name,evrParent); }else if (name=regResult[3]){ singleResult=getClasses(name,evrParent); }else if(name=regResult[4]){ singleResult=getTags(name,evrParent); } //因为此时是数组,所以使用apply改变对象指向 result.push.apply(result,singleResult); } } } return result; };代码中我已经做出了详细的注释,接下来我们做出分解,首先我们要判断selector的形式,也就是说选择器是一个字符串类型,接下来,我们并没有使用判断各个选择器形式的不同,而做出相关处理,而是用了正则表达式来进行匹配,正则表达式的用法这里不做出详细的讲解,有兴趣的可以上网查找资料,当然,如果不会正则表达式的话,用我们之前的方法,判断开头字符的方法也行,这里使用正则来进行讲解。
我们使用正则表达式的exec()的方法进行选择器检测,返回的是一个数组,如果进行匹配到的话,我们此时就要进行判断parent的类型,如果parent是字符串的话,我们将直接调用$get(parent),将parent传入,如果是一个dom节点类型,我们就直接将让他变成一个数组:
//如果匹配到 if(regResult){ parent=parent || document; var name;//用一个变量保存查找数组指定索引的元素,减少查找次数 //判断数组的元素是否有值,id:索引伪2 class:索引为3 标签:索引为4 if (typeof parent === "string"){//判断parent parent=$get(parent); }else if (parent.nodeType){//判断parent是不是一个Dom元素(dom元素都有节点) parent=[parent]; }如果都不是前边两种情况的话,parent就是一个dom数组,我们此时就将parent进行循环遍历:
for(var i=0;i<parent.length;i++){ var evrParent=parent[i]; var singleResult;//变量保存值 if(name=regResult[2]){//所要查找选择器返回的字符串是id的时候 singleResult=getId(name,evrParent); }else if (name=regResult[3]){ singleResult=getClasses(name,evrParent); }else if(name=regResult[4]){ singleResult=getTags(name,evrParent); } //因为此时是数组,所以使用apply改变对象指向 result.push.apply(result,singleResult); }使用只能正则表达式进行exec()匹配后,我们返回的是一个数组的形式,索引是2的是id,索引是3的是class,索引是4的时候是标签,所以我们进行for循环的时候,可以通过索引值进行判断是id 还是class还是标签,最后我们都要将得到的数组进行数组的push方法调用apply(),推进数组result中。