详解Jquery实现ready和bind事件
讲这一节之前,先回顾之前一段代码:
(function(win){
var_$=function(selector,context){
returnnew_$.prototype.Init(selector,context);
}
_$.prototype={
Init:function(selector,context){
this.elements=[];
varcontext=context||document;
if(context.querySelectorAll){
vararr=context.querySelectorAll(selector);
for(vari=0;i<arr.length;i++){
this.elements.push(arr[i]);
}
}
////这一块是选择器的实现,没有写完,可以自己实现
},
each:function(callback){
if(this.elements.length>0){
for(vari=0;i<this.elements.length;i++){
callback.call(this,i,this.elements[i]);
}
}
}
}
_$.prototype.Init.prototype=_$.prototype;
window.$=_$;
})(window||global);
上面我们实现了节点的查找,今天要讲的是对节点的事件绑定。
熟悉Jquery源码的TX应该知道:我们上面的代码少了ready事件,只是针对节点进行查询,并没有将document对象考虑进去。我之前单独讲过window.onload和document.ready的区别,还对document.ready事件进行了扩展。
现在我们把扩展方法加到这里面:
我们的Init方法要改正一下:
Init:function(selector,context){
this.elements=[];
if(typeofselector==="function"){
this.elements.push(document);
this.ready(selector);
}
else{
varcontext=context||document;
varisDocument=function(ele){
vartostring=Object.prototype.toString;
returntostring.call(ele)=="[objectHTMLDocument]"||"[objectDocument]";
}
if(isDocument(selector)){
this.elements.push(selector);
}
elseif(context.querySelectorAll){
vararr=context.querySelectorAll(selector);
for(vari=0;i<arr.length;i++){
this.elements.push(arr[i]);
}
}
}
}
这段代码的大致意思是:如果传入的参数selector是function类型,就执行ready事件。如果是document就将document对象插入到this.elements数组里面(这个传入之后,会在ready事件里面进行判断)。如果是字符窜,就查询出节点,循环插入到this.elements数组里面,没什么难度。主要考虑到$(document).ready和$(function(){})这两种ready事件的写法。
我们接下来把ready函数加进来:
ready:function(callback){
varisDocument=function(ele){
vartostring=Object.prototype.toString;
returntostring.call(ele)=="[objectHTMLDocument]"|"[objectDocument]";
}
if(isDocument(this.elements[0])){
if(document.addEventListener){
document.addEventListener('DOMContentLoaded',function(){
document.removeEventListener('DOMContentLoaded',arguments.callee,false);
callback();
},false);
}
elseif(document.attachEvent){
document.attachEvent('onreadystatechange',function(){
if(document.readyState=="complete"){
document.detachEvent('onreadystatechange',arguments.callee);
callback();
}
});
}
elseif(document.lastChild==document.body){
callback();
}
}
}
这段代码我之前其实讲过了(onload和ready的区别),不知道的可以看看。
现在ready事件,我们实现了。然后就可以针对节点进行事件注册了。
我们来实现bind函数,代码如下:
bind:function(type,callback){
if(document.addEventListener){
this.each(function(i,item){
item.addEventListener(type,callback,false);
});
}
elseif(document.attachEvent){
this.each(function(i,item){
item.attachEvent('on'+type,callback);
});
}
else{
this.each(function(i,item){
tem['on'+type]=callback;
});
}
}
这里面都是些兼容性代码,实现节点的事件注册。之前的each,大家可能不知道是要干嘛的。现在在这里面就用到了。
主要作用是针对节点循环做一些操作。
完整代码,来一份:
(function(win){
var_$=function(selector,context){
returnnew_$.prototype.Init(selector,context);
}
_$.prototype={
Init:function(selector,context){
this.elements=[];
if(typeofselector==="function"){
this.elements.push(document);
this.ready(selector);
}
else{
varcontext=context||document;
varisDocument=function(ele){
vartostring=Object.prototype.toString;
returntostring.call(ele)=="[objectHTMLDocument]"|"[objectDocument]";
}
if(isDocument(selector)){
this.elements.push(selector);
}
elseif(context.querySelectorAll){
vararr=context.querySelectorAll(selector);
for(vari=0;i<arr.length;i++){
this.elements.push(arr[i]);
}
}
}
},
each:function(callback){
varlength=this.elements.length;
if(length>0){
for(vari=0;i<length;i++){
callback.call(this,i,this.elements[i]);
}
}
},
ready:function(callback){
varisDocument=function(ele){
vartostring=Object.prototype.toString;
returntostring.call(ele)=="[objectHTMLDocument]"|"[objectDocument]";
}
if(isDocument(this.elements[0])){
if(document.addEventListener){
document.addEventListener('DOMContentLoaded',function(){
document.removeEventListener('DOMContentLoaded',arguments.callee,false);
callback();
},false);
}
elseif(document.attachEvent){
document.attachEvent('onreadystatechange',function(){
if(document.readyState=="complete"){
document.detachEvent('onreadystatechange',arguments.callee);
callback();
}
});
}
elseif(document.lastChild==document.body){
callback();
}
}
},
bind:function(type,callback){
if(document.addEventListener){
this.each(function(i,item){
item.addEventListener(type,callback,false);
});
}
elseif(document.attachEvent){
this.each(function(i,item){
item.attachEvent('on'+type,callback);
});
}
else{
this.each(function(i,item){
tem['on'+type]=callback;
});
}
}
}
_$.prototype.Init.prototype=_$.prototype;
window.$=_$;
})(window);
这几个函数基本上可以实现对节点的事件注册了。其余的一些特效,还需要扩展。如果感兴趣的话可以自己在 _$.prototype对象里面加方法。
以上就是本文的全部内容,希望能够帮助大家。