大概思路是这样的:通过判断传过来的参数是什么类型,如果是对象,那这里就是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. centos7上开启单用户模式

    author: headsen  chen date : 2018-08-02  11:23:16 1,在出现centos7的页面的时候,按 e进入到编译内核的界面 2,找到下面的这一段,将ro 该车 ...

  2. jhipser微服务架构介绍

    内容提要 本文涉及以下内容: 微服务架构介绍 spring cloud介绍 jhipster架构介绍 微服务架构介绍 微服务概念 微服务和SOA很相似,都是按照业务功能把系统拆分成一个一个的服务.比如 ...

  3. 【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

    [BZOJ1645][Usaco2007 Open]City Horizon 城市地平线 Description Farmer John has taken his cows on a trip to ...

  4. 最小树形图(hdu4009)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  5. postgresql----INSERT

    INSERT即向表中写入数据,每条INSERT语句可以写入一条数据,也可以写入多条数据.另外还可以将其他的查询结果集用在INSERT中,将查询结果写入表中. 测试表 test)); CREATE TA ...

  6. SpringBoot项目属性配置

    如果使用IDEA创建Springboot项目,默认会在resource目录下创建application.properties文件,在SpringBoot项目中,也可以使用yml类型的配置文件代替pro ...

  7. Tfs 2015 代理池配置笔记

    Tfs的构建代理池其实是在代理服务器上开启一个TFSBuild的代理服务,配好相关的Tfs地址后,就能在Tfs管理界面看到了. 如果是Tfs服务和发布代理是同一台服务器,具体操作详见: 安装TFS20 ...

  8. Python开发【模块】:CSV文件 数据可视化

    CSV模块 1.CSV文件格式 要在文本文件中存储数据,最简单的方式是讲数据作为一系列逗号分隔的值(CSV)写入文件,这样的文件成为CSV文件,如下: AKDT,Max TemperatureF,Me ...

  9. rpc、socket、mq

    关于RPC与MQ异同的理解 相同:1.都利于大型系统的解耦:2.都提供子系统之间的交互,特别是异构子系统(如java\node等不同开发语言):不同:1.RPC侧重功能调用,因此多半是同步的:备注:也 ...

  10. Centos7 Zabbix3.2安装

    实验环境: 阿里云 [zabbix@miyan ~]$ cat /etc/redhat-release CentOS Linux release (Core) 不得不说,官方文档确实强大 1.官方文档 ...