详解用原生JavaScript实现jQuery的某些简单功能
大致介绍
学习了妙味,用原生的JavaScript实现jQuery中的某些部分功能
定义自己的函数库lQuery
$()选择器的实现
jQuery是面向对象的,所以自己编写的也要是面向对象的,看看基本的结构
//定义lQuery对象 functionlQuery(lArg){ } functionlQ(lArg){ returnnewlQuery(lArg); } //css()方法 lQuery.prototype.css=function(){}; //html()方法 lQuery.prototype.html=function(){};
先来仿写jQuery中的$(函数)的方法
//定义lQuery对象 functionlQuery(lArg){ //用typeof判断参数的类型是function、 switch(typeoflArg){ case'function': //如果采用这种写法,给lQ绑定相同的函数,但是只会执行一次 //window.onload=lArg; //break; } }
如果写出这样的函数就会出现问题
lQ(function(){ alert(1); }); lQ(function(){ alert(2); });
这样就只会弹出'2',但是在jQuery中都会弹出,所以上面的方法不对,我们采用事件绑定的形式来解决这个问题
//绑定事件函数 functionlQbind(obj,eventName,fn){ //标准浏览器 if(obj.addEventListener){ obj.addEventListener(eventName,fn,false); }else{ //IE浏览器 obj.attachEvent('on'+eventName,fn); } }
可以使用这样调用
switch(typeoflArg){ case'function': //如果采用这种写法,给lQ绑定相同的函数,但是只会执行一次 //window.onload=lArg; //break; lQbind(window,'load',lArg); break; }
仿写jQuery中的$('.div')、$('#div')、$('div')三种方法
这三种方法的区别是第一个字符的不同,所以我们可以根据第一个字符的不同来进行区别对待
先来仿写$('.div')
//'.div' case'.': this.elements=getClass(document,lArg.substring(1)); break;
由于getElementsByClassName()是HTML5里的方法,像IE8以下不兼容所以我们自己写了一个简单的getClass方法
//获取class属性 functiongetClass(obj,name){ vararr=[]; varelems=obj.getElementsByTagName('*'); for(vari=0;i<elems.length;i++){ if(elems[i].className==name){ arr.push(elems[i]); } } returnarr; }
仿写$('#div')
case'#': this.elements.push(document.getElementById(lArg.substring(1))); break; //'.div' case'.':
仿写$('div')
default: //getElementsByTagName返回的是一个类数组NodeList,为了防止以后出现麻烦,要把他转为一个 //数组 this.elements=toArray(document.getElementsByTagName(lArg)); break;
由于getElementsByTagName返回的是一个类数组NodeList,为了防止以后出现麻烦,要把他转为一个数组,自定义了一个toArray方法
//将一个类数组转为真正的数组 functiontoArray(lickArr){ vararr=[]; for(vari=0;i<lickArr.length;i++){ arr.push(lickArr[i]); } returnarr; }
仿写$(对象)的方法
//window document
case'object':
this.elements.push(lArg);
break;
html()的实现
html()方法分为有参和无参
//html()方法 lQuery.prototype.html=function(str){ if(str){//设置 for(vari=0;i<this.elements.length;i++){ this.elements[i].innerHTML=str; } }else{ returnthis.elements[0].innerHTML; } returnthis; };
on()方法的实现
利用前面实现的绑定函数可以很容易的实现
lQuery.prototype.on=function(eventName,fn){
for(vari=0;i<this.elements.length;i++){
lQbind(this.elements[i],eventName,fn);
}
}
click()和mouseover()方法的实现
利用on()方法可以容易的实现
//click()方法 lQuery.prototype.click=function(fn){ this.on('click',fn); returnthis; } //mouseover()方法 lQuery.prototype.mouseover=function(fn){ this.on('mouseover',fn); returnthis; }
hide()和show()方法的实现
//hide()方法 lQuery.prototype.hide=function(){ for(vari=0;i<this.elements.length;i++){ this.elements[i].style.display='none'; } returnthis; } //show()方法 lQuery.prototype.show=function(){ for(vari=0;i<this.elements.length;i++){ this.elements[i].style.display='block'; } returnthis; }
hover()方法的实现
//hover()方法 lQuery.prototype.hover=function(fnover,fnout){ this.on('mouseover',fnover); this.on('mouseout',fnout); returnthis; }
css()方法的实现
实现$('div').css('width')和$('div').css('width','200px')
lQuery.prototype.css=function(attr,value){ if(arguments.length==2){ for(vari=0;i<this.elements.length;i++){ this.elements[i].attr=value; } } if(arguments.length==1){ returngetStyle(this.elements[0],attr); } }
定义了getStyle()方法是为了能找到行内样式以外的样式
//获取属性 functiongetStyle(obj,attr){ if(obj.currentStyle[attr]){ obj.currentStyle[attr]; }else{ obj.getComputedStyle(obj,false)[attr]; } }
attr()方法的实现
用了和css()不同的方法
//attr()方法 lquery.prototype.attr=function(attr,value){ if(arguments.length==2){//设置 for(vari=0;i<this.elements.length;i++){ this.elements[i].setAttribute(attr,value); } } elseif(arguments.length==1){//获取 returnthis.elements[0].getAttribute(attr); } returnthis; };
eq()方法的实现
实现$('div').eq(1)
由于eq()方法返回的对象要操作许多lQuery的方法,所以返回的对象必须是lQuery对象
lQuery.prototype.eq=function(num){ returnlQ(this.elements[num]); };
index()方法的实现
实现$('div').index()返回这个元素在同辈元素中的位置
lQuery.prototype.index=function(){ varelems=this.elements[0].parentNode.children; for(vari=0;i<elems.length;i++){ if(elems[i]==this.elements[0]){ returni; } } };
阻止默认事件和阻止事件冒泡
在jQuery中returnfalse是阻止默认事件和事件冒泡,所以我们要对lQbind函数进行修改,通过判断绑定的函数的返回值是否为false来判断是否要进行阻止默认事件和阻止事件冒泡
functionlQbind(obj,events,fn){ if(obj.addEventListener){ obj.addEventListener(events,function(ev){ if(fn()==false){ ev.preventDefault(); ev.cancelBubble=true; } },false); } else{ obj.attachEvent('on'+events,function(){ if(fn()==false){ window.event.cancelBubble=true; returnfalse; } }); } }
find()方法的实现
仿写$('div').find('.box')和$('div').find('#box')方法
这里涉及到通过判断find()参数第一个字符的方法来进行不同的操作和$()方法差不多,在循环时要使用concat()方法来连接数组,最后返回一个lQuery对象
lQuery.prototype.find=function(sel){ vararr=[]; if(sel.charAt(0)=='.'){ for(vari=0;i<this.elements.length;i++){ arr=arr.concat(getClass(this.elements[i],sel.substring(1))); } } else{ for(vari=0;i<this.elements.length;i++){ arr=arr.concat(toArray(this.elements[i].getElementsByTagName(sel))); } } returnlQ(arr); };
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!