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. [BZOJ 2038]小Z的袜子

    传送门:BZOJ 2038 题意很明确,是在给定的区间内任意选取两个数,求选到两个相同的数的概率. 所以我们得首先统计在给定的区间内,相同的数对有多少对,那么这里就使用到了莫队算法.如果对莫队算法还不 ...

  2. POJ 2653

    题目大意:一个小孩不断往地上扔棍子,共n根,求结束后共有多少根不与去他相交. 解法思路:典型的判断线段相交问题,利用快速排斥+双跨立判断相交,最后输出没相交的. (图片来源:http://www.2c ...

  3. LPTHW 笨办法学python 40章 类

    今天读了LPTHW的第40章以后豁然开朗,原来一直愚钝,不太理解类的定义和使用,还有就是不太理解关于self的定义. class MyStuff(object): def __init__(self) ...

  4. 在windows下配置wnmp

    1.下载mysql 2.下载php 3.下载nginx 4.创建文件夹wnmp 把php,nginx,mysql放到wnmp目录下,另外新建www目录, 用于存放web文件 配置nginx,如下(ng ...

  5. JAVA,NET RSA密钥格式转换

    JAVA和NET RSA密钥格式相互转换(公钥,私钥) 做了一个小项目遇到java和.net非对称加密问题,java的公钥和私钥就直接是一个字符串的形式展示的,但是.net是以xml简单包裹形式展示的 ...

  6. 6.Counting Point Mutations

    Problem Figure 2. The Hamming distance between these two strings is 7. Mismatched symbols are colore ...

  7. mysql 完整性约束

    mysql 完整性约束 数据的完整性概述根据完整性实施的方法将完整性约束分为四类:1.实体完整性 实体完整性的实现:通过在表中设置主键约束.唯一约束或标识列来实现 主键约束:应用于表列的一个约束 用法 ...

  8. ubuntu绑定串口设备

    原创博文:转载请标明出处:http://www.cnblogs.com/zxouxuewei 为了不让我们的usb设备在使用时,由于设备节点注册的ID不同,设备名称会不同,设备如何在 Linux 中永 ...

  9. ubuntu 安装git服务器

    ubuntu14.04安装git,搭建环境 1.sudo apt-get install git 2.生成key ssh-keygen -t rsa 3.保存其他用户,创建的ssh用户密码 cd .s ...

  10. ASP.NET Razor - C# 变量

    变量是用来存储数据的命名实体. 变量 变量是用来存储数据的. 一个变量的名称必须以字母字符开头,并且不能包含空格或者保留字符. 一个变量可以是一个指定的类型,表示它所存储的数据类型.string 变量 ...