【学】jQuery的源码思路1——后代选择器
jQuery的源码思路1——后代选择器
这里探讨一下jQuery中后代选择器的封装原理,并自己写一下
getEle('#div1 ul li .box');接受的参数就是个后代选择器,类似于这样:
#div1 ul li .boxid/tagname/classdiv#div1div.boxinput[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——后代选择器的更多相关文章
- 【学】jQuery的源码思路2——$符号是如何封装的
jQuery中的$符号功能很强大,原因在于对函数参数的个数以及种类的控制,还有对于面向对象思想的运用 function jQuery(args){ //接受参数,并对其判断 this.elements ...
- 【学】jQuery的源码思路4——增加一些功能
本文说一些简单的jQuery实现原理 eq() get() hide() show() index() find() //返回找到的一组元素中的第n个 zQuery.prototype.eq=func ...
- 【学】jQuery的源码思路3——添加事件及其他
这段添加的方法有: 各类事件函数 css() addEvent() toggle() //添加各种事件,将常用的事件名称放入数组,然后循环着加入到zQuery对象的原型上 var eventArr = ...
- 【学】jQuery的源码思路6——增加each,animaion,ajax以及插件机制
each() 插件机制 animation ajax //each() //这里第一个参数指定将this指向每次循环到的那个元素身上,而第三个参数element其实就是this本身所以和第一个参数是一 ...
- 【学】jQuery的源码思路5——增加class的操作
hasClass, addClass, removeClass, toggleClass //addClass,加入class会对元素,利用正则,将class中多余的空格去掉 zQuery.proto ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- jQuery.attributes源码分析(attr/prop/val/class)
回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和p ...
- 【深入浅出jQuery】源码浅析2--奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 深入分析,理解jQuery.Deferred源码
前言: 如果你对jQuery.Callback回调对象不了解,或者只掌握其方法,但是没有通过阅读源码理解,可以先阅读 前一章jQuery.Callbacks源码解读二,因为只有完全理解jQuery.C ...
随机推荐
- shell脚本入门及基本元素
命令和参数 #!/bin/sh 其中#!用来告诉系统它后面的参数是用来执行该文件的程序,必须放在脚本的首行,不然会在执行脚 本 的时候报错.当一个文件开头的两个字符是#!时,内核会扫描其它的部分看是否 ...
- MVC 架构
MVC 模式是一种严格实现应用程序个部分隔离的框架模式.这种"隔离"也叫"分离关注点" 通俗名称:"松耦合" 松耦合的应用程序价格设计方式, ...
- 关于如何通过json更改背景图片
今天遇到的问题,突然脑子就不灵光了,平时我们在用jquery更改元素css样式,特别是background的时候,通常用的代码 $("body").css("backgr ...
- Android studio快捷键大全 和 eclipse对照(原)
Ctrl+空格 代码提示 (同Eclipse中Alt+/) Ctrl+Shjft+N 项目 ...
- Redis中struct运用
c#操作缓存例如redis比较推荐ServiceStack 在redis中运用key-value存储数据,但是遇到结构体该如何处理,是类可通过get<type>(key)获得,那struc ...
- ArcGIS图层介绍
什么是图层 图层是用来在 ArcGIS 产品套件中显示地理数据集的机制.每个图层代表一种数据集(可以是地图服务.图形或是矢量数据),并指定该数据集是如何描绘使用一组属性的. 包含一个地图控件的每个应用 ...
- PHP Web Shell in browser
/************************************************************************************* * PHP Web She ...
- (原创)VM中的CentOS6.4中安装CloudStack6.3②
接着VM中的CentOS6.4中安装CloudStack6.3①中文章接着,往下面安装 4.更新 yum 仓库 默认情况下,CentOS的软件源中没有收录最新版本CloudStack,为了能顺利安装, ...
- Lua IO库详解
I/O 库提供了两套不同风格的文件处理接口. 第一种风格使用隐式的文件句柄: 它提供设置默认输入文件及默认输出文件的操作, 所有的输入输出操作都针对这些默认文件. 第二种风格使用显式的文件句柄. 当使 ...
- mongodb字段类型转化
最近在使用mongoDB, 发现mongo对字段类型的定义并不是很严格,完全依赖传入数据的类型,在加上PHP是弱类型的语言,所以难免会出现一些错误.如果预想的类型是Int型,但数据存储的是String ...