jQuery的源码思路1——后代选择器

这里探讨一下jQuery中后代选择器的封装原理,并自己写一下

getEle('#div1 ul li .box');接受的参数就是个后代选择器,类似于这样:

  • #div1 ul li .box
  • id/tagname/class
  • div#div1
  • div.box
  • input[type=button]
  • li:eq(3)/lt(3)/gt(3)
  • li:first/last/odd/even
function getEle(str){
var arr = str.match(/\S+/g); //先把传进的字符串用正则匹配一下,把多余的空格去掉再放进数组,知识点:match返回的是一个数组,这里也可以用split,split也可以放正则,但是要用小写's+'
var aParent = [document]; //一开始以document为父级,但是也要放在数组中
var aChild = [];
for(var i=0 ;i<arr.length; i++){//切好后的数组,循环,每次把抓到的数据放到aChild中,再把它赋给下一次循环的父级
aChild = getByStr(aParent,arr[i]); //需要一个函数,传入父级以及要抓该父级下字符串为第二个参数的元素,抓到的元素赋给数组aChild
aParent = aChild;//然后将该数组作为下一个循环的父级
}
return aChild;
} function getByStr(aParent,str){
var aChild = [];
for (var i=0; i<aParent.length; i++){
switch (str.charAt(0)){ //判断字符串是否含有#.或者没有,分别代表id,class和标签
case '#':
var obj = aParent[i].getElementById(str.substring(1));
obj && aChild.push(obj);
break;
case '.':
var aEle = getByClass(aParent[i],str.substring(1));
for(var j=0; j<aEle.length; j++){
aChild.push(aEle[j]);
}
break;
default:
//div#div1
if(/\w+#\w+/.test(str)){
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]);
break; //只抓一个
}
}
}else if(/\w+\.\w+/.test(str)){
var arr = str.split('.');
var aEle = aParent[i].getElementsByTagName(arr[0]);
var re = new RegExp('\\b' + arr[1] + '\\b'); //用边界的正则是为了避免出现class中出现多个空格,所以只要找到即可
for(var j=0; j<aEle.length; j++){
if(re.test(aEle[j].className)){
aChild.push(aEle[j]);
}
}
}else if(/\w+\[\w+\=\w+]/.test(str)){ //input[type=button]
var arr = str.split(/\[|\=|\]/); // ['input','type','button',]
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]);
}
}
}else if(/\w+\:\w+(\(.\))?/.test(str)){
var arr = str.split(/\:|\(|\)/);//[tag,eq,3][tag,first]
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 '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++){
if(j%2==0){
aChild.push((aEle[j]));
}
}
break;
case 'eq':
aEle[arr[2]] && aChild.push(aEle[arr[2]]);
break;
case 'lt':
for(var j=0; j<arr[2]; j++){
aChild.push(aEle[j]);
}
break;
case 'gt':
for(var j=Number(arr[2])+1;j<aEle.length; j++){
aChild.push(aEle[j]);
}
break;
} }else{
var aEle = aParent[i].getElementsByTagName(str);
for(var j=0; j<aEle.length; j++)
aChild.push(aEle[j]);
}
}
}
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;
}

【学】jQuery的源码思路1——后代选择器的更多相关文章

  1. 【学】jQuery的源码思路2——$符号是如何封装的

    jQuery中的$符号功能很强大,原因在于对函数参数的个数以及种类的控制,还有对于面向对象思想的运用 function jQuery(args){ //接受参数,并对其判断 this.elements ...

  2. 【学】jQuery的源码思路4——增加一些功能

    本文说一些简单的jQuery实现原理 eq() get() hide() show() index() find() //返回找到的一组元素中的第n个 zQuery.prototype.eq=func ...

  3. 【学】jQuery的源码思路3——添加事件及其他

    这段添加的方法有: 各类事件函数 css() addEvent() toggle() //添加各种事件,将常用的事件名称放入数组,然后循环着加入到zQuery对象的原型上 var eventArr = ...

  4. 【学】jQuery的源码思路6——增加each,animaion,ajax以及插件机制

    each() 插件机制 animation ajax //each() //这里第一个参数指定将this指向每次循环到的那个元素身上,而第三个参数element其实就是this本身所以和第一个参数是一 ...

  5. 【学】jQuery的源码思路5——增加class的操作

    hasClass, addClass, removeClass, toggleClass //addClass,加入class会对元素,利用正则,将class中多余的空格去掉 zQuery.proto ...

  6. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  7. jQuery.attributes源码分析(attr/prop/val/class)

    回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和p ...

  8. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  9. 深入分析,理解jQuery.Deferred源码

    前言: 如果你对jQuery.Callback回调对象不了解,或者只掌握其方法,但是没有通过阅读源码理解,可以先阅读 前一章jQuery.Callbacks源码解读二,因为只有完全理解jQuery.C ...

随机推荐

  1. window 下如何安装ghost博客

    1.安装nodejs # Node v0.12.x and v4.2+ LTS - supported 我本地安装的是4.2 安装其他版本可能提示系统不兼容 2.安装mysql 3.安装bower 4 ...

  2. SQLServer将表数据导出为Insert语句

    从网上找到的方法,不过很不错,记录下来,也算是分享下~~ 有一个表,city,有列:cityID,cityName;将此表中所有数据,变为insert语句 select 'insert into ta ...

  3. Thinkpad T420 指纹开机 win10 解决方案

    以前没感觉笔记本上的指纹有什么用,后来无意看到了指纹能开机.便尝试把这个功能给用起来.果然麻烦了些. 1.官网上没有win10的指纹应用软件. 下载了win8的版本,安装后没有问题,可以登录win10 ...

  4. DOM和IE中的 事件对象

    DOM中的事件对象:(符合W3C标准)    preventDefault()        取消事件默认行为    stopImmediatePropagation() 取消事件冒泡同时阻止当前节点 ...

  5. c++ 顺序容器学习

    所谓容器,就是一个装东西的盒子,在c++中,我们把装的东西叫做“元素” 而顺序容器,就是说这些东西是有顺序的,你装进去是什么顺序,它们在里面就是什么顺序. c++中的顺序容器一共有这么几种: vect ...

  6. WebMidiLink

    g200kg > WebMidiLink > 1.Introduction WebMidiLink 2012/06/26 1.Introduction « Prev 1.Introduct ...

  7. web发布 将各个文件夹输出合并到其自己的程序集 注意事项

    今天在发布web网站的时候 使用了“将各个文件夹输出合并到其自己的程序集”的选项,如图: 开始在 程序集前缀(可选)处,没有填写内容. 发布到IIS后出现未加载到程序集xxxx的错误. 经过各种调试, ...

  8. 转载《Android-TabHost 选项卡功能用法详解》

    一. TabHost介绍 TabHost组件可以在界面中存放多个选项卡, 很多软件都使用了改组件进行设计; 1. TabHost常用组件 TabWidget : 该组件就是TabHost标签页中上部 ...

  9. CentOS7 搭建python3 Django环境

    yum install gcc yum install make yum install openssl-devel -y yum install sqlite-devel -y wget https ...

  10. java 三个循环的优缺点

    package cc.knms.appservice.test; import java.text.ParseException; import java.util.ArrayList; import ...