【学】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 ...
随机推荐
- HDU 4920 居然会超时
题意:求两个n*n的矩阵相乘的结果,得出的每个元素%3: 分析:2000ms然后n的范围是800,我们自己估算的时间复杂度并不会超时,但是结果就是超时了. #include <cstdio> ...
- 转的: 重绘ListView 修改标题颜色
1.owerDraw 设置为true 2.实现事件 DrawColumnHeader DrawItem DrawSubItem private void listView1_DrawColumnHea ...
- Discuz对不起,您安装的不是正版应用的解决办法
方法三(2014年新增最简单方法.) .打开/source /function/function_cloudaddons.php这个文件,2.搜索:cloudaddons_validator,3.一般 ...
- EasyUI 开发笔记(二)
接上篇 :EasyUI 开发笔记(一) (http://www.cnblogs.com/yiayi/p/3485258.html) 这期就简单介绍下, easyui 的 list 展示, 在easy ...
- webview加载h5,关闭activity时,窗体泄露问题
问题描述: webview加载一个含有input控件的html页面,当点击input控件是回调app的closepage方法[closepage中只有一个finish操作],出现窗体泄露问题. 分析: ...
- win32自绘按钮,使用GDI+(三)
解决前面的问题.实现鼠标移动进入到按钮的特效. 效果是这样的 鼠标移到按钮上,改变按钮的颜色(这里用的是直接换贴在按钮上的图片) 程序运行 鼠标进入按钮 代码 #ifndef ULONG_PTR // ...
- ScriptableObject本地序列化后重启Unity后报The associated script can not be loaded.Please fix any compile errors and assign a valid script的坑
踩坑 做编辑器一些设置序列化存在本地的时候,继承自ScriptableObject的类通过 创建的asset文件. 在重启Unity后查看这个asset发现上面的所有序列化属性丢失,报的错就是 在不存 ...
- Spring Boot整合Activiti,查看流程图出现中文乱码问题
最近研究SpringBoot 整合Activiti时,实现流程图高亮追踪是出现中文乱码问题,找了很多方法,现在把我最后的解决方法提供给大家. Spring Boot是微服务快速开发框架,强调的是零配置 ...
- Git Windows客户端保存用户名与密码
1. 在Windows中添加一个HOME环境变量,值为%USERPROFILE%,如下图: 2. 在“开始>运行”中打开%Home%,新建一个名为“_netrc”的文件. 3. 用记事本打开_n ...
- java基础小知识
1.1常量: 基本数据类型常量 字符常量 整数常量的表现形式:一进制的形式来表示(二进制,八进制,十进制,十六进制) 生活中:十进制(0-9) ,星期(七进制(0-6)) ,时间(十二进制(0-11 ...