封装类似jQuery的选择器
在原生js中,我们通常都是使用getElementById,getElementsByName,getElementsByTagName,getElementsByClassName等方法来进行DOM元素的选取,这样的话如果要选取一些复杂一点的元素就需要写很长的一条语句,看到CSS3和jQuery的选择器有没有觉得很方便呢?
感谢选择器API的产生,这使得我们现在也可以很轻易的封装一个类似jQuery一样的选择器。选择器API主要有两个方法,分别是:document.querySelector,document.querySelectorAll两个方法,前者用于选取单个元素,后者可选取一个类数组的对象。具体区别可自行点击链接进行查看。
在以前的版本中,这两个方法都只能在document对象上进行调用,如果直接把该方法赋值给另一个变量就会报错,所以不管是为了兼容性,还是为了更好的扩展,我这里使用了间接的方式来进行元素的选取。
大家也知道,jQuery的选择器选取的元素并不是原生的DOM元素,而是一个类数组的形式,并且通过索引就可以转换为原生的DOM元素。除此之外,还可以进行链式调用,轻松操作DOM,可靠的事件机制等等。那么我今天就在这里用构造函数和继承来教大家实现类似的一个函数(当然只是最基础的选择器封装,其他的就需要自己扩展了,较为完整的可以去我的github进行浏览)。
首先,就是最关键的构造函数了,代码如下:
function _$(selector) {
var t=this;
var eles=Array.prototype.slice.call(document.querySelectorAll(selector),0);
eles.map(function(_v,_i) {
t[_i]=_v;
});
t.length=eles.length;
return t;
}
function $(selector) {
return new _$(selector);
}
在_$构造函数中,先用document.querySelectorAll(selector)选取相应的元素,再将这些元素转换为真正的数组,使用数组的map方法将元素一次放入this中,然后将这些元素的长度也赋值给this,最后再用真正的选择器函数进行一个小小的封装,一个选择器函数就这样诞生了。当然了,还是太简陋了,需要进一步完善。
主要完善的地方有如下几点:
类似css的多个选择器,需要对传入的参数使用split(“,”)进行分割。
传入的参数为DOM原生对象时,可将其作为this[0],然后length=1;
传入的参数为封装的对象时,可直接返回;
完整代码如下:
var $=(function() {
var $=function(selector) {
return new _$(selector);
},_$=function(selector) {
var t=this;
if(typeof selector=='string') {
var args=selector.split(","),
arr=[],
index=0;
args.map(function(v,i) {
var eles=Array.prototype.slice.call(document.querySelectorAll(v),0);
eles.map(function(_v,_i) {
t[index]=_v;
index=index+1;
})
});
t.length=index;
} else {
if(selector.length) {
return selector;
} else if($.isObeject(selector)) {
t[0]=selector;
t.length=1;
}
}
return t;
};
_$.prototype.map=function(fn) {
var t=this;
for(var i=0,len=this.length;i<len;i++) {
fn(t[i],i);
}
}
_$.prototype.html=function(html) {
var t=this;
t.map(function(v,i) {
v.innerHTML=html;
})
}
$.fn={};
$.fn.extend=function(name,fn) {
_$.prototype[name]=fn;
}
$.fn.extend("addClass",function(args) {
var c=args.split(","),t=this;
for(var i=0,len=this.length;i<len;i++) {
(function(index) {
c.map(function(v,_i) {
t[index].classList.add(v);
});
})(i);
}
return this;
});
$.fn.extend("removeClass",function(args) {
var c=args.split(","),t=this;
for(var i=0,len=this.length;i<len;i++) {
(function(index) {
c.map(function(v,_i) {
t[index].classList.remove(v);
});
})(i);
}
return this;
});
$.isArray=function() {
return Object.prototype.toString.call(value)=="[object Array]";
};
$.isObject=function() {
return Object.prototype.toString.call(value)=="[object Object]";
};
$.toArray=function(obj) {
return Array.prototype.slice.call(obj,0);
};
return $;
})();
所有代码可到我的github进行浏览。