纯JavaScript实现简易版的jQuery选择器,支持链式调用

原创
2017/06/19 00:30
阅读数 820

jQuery是一个高端而不失奢华的框架。奇特的设计思想使其通过链式调用而显得更加整洁。不过这种链式模式是基于原型继承的,并且在每一个原型方法的实现上都返回当前对象this,使当前对象一直处于原型链作用域的顶端。这样即可实现链式调用。

本文基于原型式继承实现了一个类似jQuery的选择器。源码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
	<meta charset="utf-8">
	<style>
		#containers div {
			margin-right: 5px;
			border:solid 1px blue;
			padding: 5px;
			float: left;
		}
	</style>
</head>
<body>
 <div id="container"></div>
 <span id="tspan" name="nspan">test</span>
 <script type="text/javascript">
 //小试牛刀,JavaScript的原型式继承
 var A = function(){
 	return A.fn;
 }
 A.fn = A.prototype = { //为了减少变量的创建,直接将A的原型作为A的一个属性fn
 	length:2,
 	size:function(){
 		return this.length;
 	}
 }
 console.log(A().size());

//一个简易版jQuery选择器
 var $ = function(selector,context){
 	return new $.fn.init(selector,context);
 }
 $.fn = $.prototype = {
 	constructor:$,//强化构造器,将__proto__指向$
 	push:[].push,
 	sort:[].sort,
 	splice:[].splice,
 	init : function(selector,context){
 		this.length = 0,
 		context = context || document;
 		//如果是id选择符,按位非将-1转化为0,转化为布尔值false
 		if(~selector.indexOf("#")){
 			this[0] = document.getElementById(selector.slice(1));
 			this.length = 1;
 		} else {
 			var doms = context.getElementsByTagName(selector),
 			i=0,
 			len = doms.length;
 			for(;i<len;i++){
 				this[i] = doms[i];
 			}
 			this.length = len;
 		}
 		this.context = context;
 		this.selector = selector;

 		return this;
 	},
 	length:2,
 	size:function(){
 		return this.length;
 	}
 }
 $.fn.init.prototype = $.fn;//将构造函数的原型指向一个已存在的对象

//方法拓展
$.extend = $.fn.extend = function(){
	var i=1,//拓展对象从第2个参数算起
	len = arguments.length,
	target = arguments[0],//第1个对象为源对象
	j;
	if(i == len){//如果只有1个参数
		target = this;//源对象为当前对象
		i--;
	}
	for(;i<len;i++){
		for(j in arguments[i]){
			target[j] = arguments[i][j];//拓展源对象
		}
	}
	return target;
}
//1、拓展监听事件
$.fn.extend({
	on:(function(){
		if(document.addEventListener){
			return function(type,fn){
				var i = this.length - 1;
				for(;i>=0;i--){
					this[i].addEventListener(type,fn,false);
				}
				return this;
			}
		}
	})()
});
//2、拓展attr方法
$.fn.extend({
	attr:function(){
		var arg = arguments,
		len = arg.length;
		if(this.length < 1){
			return this;
		}
		if(len === 1){ //如果只有1个参数
			if(typeof arg[0] === 'string'){//为string则获取第一个元素的属性值
				return this[0].getAttribute(arg[0]);
			} else if(typeof arg[0] === 'object'){ //获取设置的多个属性值
				for(var i in arg[0]){
					for(var j = this.length - 1;j>=0;j--){
						this[j].setAttribute(i,arg[0][i]);
					}
				}
			}
		} else if(len === 2){ //2个参数则设置属性
			for(var j=this.length-1;j>=0;j--){
				this[j].setAttribute(arg[0],arg[1]);
			}
		}
		return this;
	}
});
//3、拓展html方法
$.fn.extend({
	html:function(){
		var arg = arguments,
		len = arg.length;
		if(len === 0){
			return this[0] && this[0].innerHTML;
		} else {
			for(var i=this.length-1;i>=0;i--){
				this[i].innerHTML = arg[0];
			}
		}
		return this;
	}
});

//使用方法:获取值
 console.log($("#tspan").attr("name"));//输出nspan
 console.log($("#tspan").html());//输出test

 //设置值,链式操作
 $("span").attr("class","demo").html("add html").on("click",function(){
 	console.log("已被点击...");
 });
 </script>

</body>

</html>

执行结果:

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部