大概思路是这样的:通过判断传过来的参数是什么类型,如果是对象,那这里就是this(因为封装是自己用的,肯定不会随便乱传一个对象过来),如果是一个函数(匿名函数),那就是Dom加载(这里先不讲),如果是字符串,那就是CSS选择器,通过判断是否存在空格,没有就是单一CSS选择器,有就是后代选择器。然后再通过判断是ID选择器,类选择器还是元素选择器来执行具体的操作:

这里创建一个构造函数实现基础库Jr :

function Jr(){

}

在其原型上添加方法:

//获取ID节点
Jr.prototype.getId = function(id){
return document.getElementById(id);
} //获取CLASS节点数组
Jr.prototype.getClass = function(className, parentNode){
var node = null; //存放父节点
var temps = [];
if(parentNode != undefined){ //存在父节点时
node = parentNode;
} else { //不存在则默认document
node = document;
}
var all = node.getElementsByTagName('*');
for(var i = 0; i < all.length; i++){
//遍历所有节点,判断是否有包含className
if((new RegExp('(\\s|^)' + className + '(\\s|$)')).test(all[i].className)){
temps.push(all[i]);
}
}
return temps;
} //获取元素节点数组
Jr.prototype.getTagName = function(tag, parentNode){
var node = null; //存放父节点
var temps = [];
if(parentNode != undefined){
node = parentNode;
} else {
node = document;
}
var tags = node.getElementsByTagName(tag);
for(var i = 0; i < tags.length; i++){
temps.push(tags[i]);
}
return temps;
}

接下来就是在构造函数里通过传参来进行一系列选择器操作:

//基础库
function Jr(args){
//创建一个数组,用来保存获取的节点或节点数组
this.elements = [];
//当参数是一个字符串,说明是常规css选择器,不是this,或者function
if(typeof args == 'string'){
//css模拟,就是跟CSS后代选择器一样
if(args.indexOf(' ') != -1){
//把节点拆分开并保存在数组里
var elements = args.split(' ');
//存放临时节点对象的数组,解决被覆盖问题
var childElements = [];
var node = []; //用来存放父节点用的
for(var i = 0; i < elements.length; i++){
//如果默认没有父节点,就指定document
if(node.length == 0) node.push(document);
switch(elements[i].charAt(0)) {
//id
case '#' :
//先清空临时节点数组
childElements = [];
childElements.push(this.getId(elements[i].substring(1)));
node = childElements; //保存到父节点
break;
//类
case '.' :
childElements = [];
//遍历父节点数组,匹配符合className的所有节点
for(var j = 0; j < node.length; j++){
var temps = this.getClass(elements[i].substring(1), node[j]);
for(var k = 0; k < temps.length; k++){
childElements.push(temps[k]);
}
}
node = childElements;
break;
//标签
default :
childElements = [];
for(var j = 0; j < node.length; j++){
var temps = this.getTagName(elements[i], node[j]);
for(var k = 0; k < temps.length; k++){
childElements.push(temps[k]);
}
}
node = childElements; }
}
this.elements = childElements;
} else {
//find模拟,就是说只是单一的选择器
switch(args.charAt(0)) {
case '#':
this.elements.push(this.getId(args.substring(1)));
break;
case '.':
this.elements = this.getClass(args.substring(1));
break;
default :
this.elements = this.getTagName(args);
}
}
} else if(typeof args == 'Object'){
if(args != undefined){
this.elements[0] = args;
}
} else if(typeof args == 'function'){
//这里不讲
this.ready(args);
}
}

最后,我们调用该基础库:

//调用
var $ = function(args){
return new Jr(args);
}

现在,我们就可以实现如下选择器等效果了:

$(this)
$('#box')
$('.box')
$('div')
$('#box div .nav')
$('.box .nav p')

JS封装简单后代选择器的更多相关文章

  1. 原生JS封装简单动画效果

    原生JS封装简单动画效果 一致使用各种插件,有时候对原生JS陌生了起来,所以决定封装一个简单动画效果,熟悉JS原生代码 function animate(obj, target,num){ if(ob ...

  2. 关于js封装框架类库之选择器引擎(二)

    在上篇介绍了选择器的获取标签.id.类名的方法,现在我们在上篇基础上继续升级 1.问题描述:上篇get('选择器')已经实现,如果get方法里是一个选择器的父元素,父元素是DOM对象,那么如何获取元素 ...

  3. JS的简单用法

    JS的简单用法 参考:http://www.w3school.com.cn/js/js_switch.asp JavaScript 是网络的脚本语言 JavaScript 是可插入 HTML 页面的编 ...

  4. 第一百三十九节,JavaScript,封装库--CSS选择器

    JavaScript,封装库--修改元素选择器 就是将构造库函数修改成元素选择器,像css那样,输入#xxx .xxx xxx  (获取指定id下的指定class下的指定标签元素) 修改后的基础库 / ...

  5. jQuery---jq基础了解(语法,特性),JQ和JS的区别对比,JQ和JS相互转换,Jquery的选择器(基础选择器,层级选择器,属性选择器),Jquery的筛选器(基本筛选器,表单筛选器),Jquery筛选方法

    jQuery---jq基础了解(语法,特性),JQ和JS的区别对比,JQ和JS相互转换,Jquery的选择器(基础选择器,层级选择器,属性选择器),Jquery的筛选器(基本筛选器,表单筛选器),Jq ...

  6. 原生JS封装Ajax插件(同域&&jsonp跨域)

    抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...

  7. 使用NW.js封装微信公众号菜单编辑器为桌面应用

    开发微信公众号的朋友都会遇到一个常见的需求就是修改自定义菜单,如果每个人都去开发这个不经常使用的功能确实有点浪费时间.前段时间在github上找到一个仿企业号的菜单编辑界面,结合微信的C# SDK开发 ...

  8. 用jQuery基于原生js封装的轮播

    我发现轮播在很多网站里面都用到过,一个绚丽的轮播可以为网页增色不少,最近闲来无事,也用原生js封装了一个轮播,可能不像网上的插件那么炫,但是也有用心去做.主要用了闭包的思想.需要传递的参数有:图片地址 ...

  9. 【学】jQuery的源码思路1——后代选择器

    jQuery的源码思路1--后代选择器 这里探讨一下jQuery中后代选择器的封装原理,并自己写一下 getEle('#div1 ul li .box');接受的参数就是个后代选择器,类似于这样: # ...

随机推荐

  1. 【PHP+Redis】 php-redis 操作类 封装

    <?php /** * redis操作类 * 说明,任何为false的串,存在redis中都是空串. * 只有在key不存在时,才会返回false. * 这点可用于防止缓存穿透 * */ cla ...

  2. MUI ajax数据请求(list)

    服务器返回格式 { "code": "1001", "message": "查询成功", "data" ...

  3. vux报错二

    执行npm run build后 "build": "node build/build.js",   // 输出提示信息 - 提示用户请在 http 服务下查看 ...

  4. Java初学者笔记六:反射

    Java反射基础 零.基础类代码 import java.io.*; import java.lang.reflect.*; class father{ public String fName; fa ...

  5. 【BZOJ4401/3004】块的计数/吊灯 乱搞

    [BZOJ4401]块的计数 Description 小Y最近从同学那里听说了一个十分牛B的高级数据结构——块状树.听说这种数据结构能在sqrt(N)的时间内维护树上的各种信息,十分的高效.当然,无聊 ...

  6. 【BZOJ2901】矩阵求和

    Description 给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和. Input 第一行两个正整数n,m. 接下来n行,每行n个非负整数,表示第一个矩阵. 接下来n行,每行n个非负整数 ...

  7. java如何随机生成定长的字符串

    小数,字符串.时间等示例代码 String base = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 public c ...

  8. 静态绑定 self 和 static的区别

    后期静态绑定 自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类. 准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwar ...

  9. Python开发【模块】:Concurrent

    concurrent 模块 回顾: 对于python来说,作为解释型语言,Python的解释器必须做到既安全又高效.我们都知道多线程编程会遇到的问题,解释器要留意的是避免在不同的线程操作内部共享的数据 ...

  10. 正则表达式python

    import re # re.match() 能够匹配出以xxx开头的字符串 ret = re.match(r"H", "Hello Python") # pr ...