詳解用原生JavaScript實(shí)現(xiàn)jQuery的某些簡(jiǎn)單功能
大致介紹
學(xué)習(xí)了妙味,用原生的JavaScript實(shí)現(xiàn)jQuery中的某些部分功能
定義自己的函數(shù)庫(kù)lQuery
$()選擇器的實(shí)現(xiàn)
jQuery是面向?qū)ο蟮?,所以自己編?xiě)的也要是面向?qū)ο蟮?,看看基本的結(jié)構(gòu)
// 定義lQuery對(duì)象 function lQuery(lArg){ } function lQ(lArg){ return new lQuery(lArg); } // css()方法 lQuery.prototype.css = function(){}; // html()方法 lQuery.prototype.html = function(){};
先來(lái)仿寫(xiě)jQuery中的$(函數(shù))的方法
// 定義lQuery對(duì)象 function lQuery(lArg){ // 用typeof判斷參數(shù)的類(lèi)型是 function 、 switch( typeof lArg){ case 'function': // 如果采用這種寫(xiě)法,給lQ綁定相同的函數(shù),但是只會(huì)執(zhí)行一次 // window.onload = lArg; // break; } }
如果寫(xiě)出這樣的函數(shù)就會(huì)出現(xiàn)問(wèn)題
lQ(function(){ alert(1); }); lQ(function(){ alert(2); });
這樣就只會(huì)彈出'2',但是在jQuery中都會(huì)彈出,所以上面的方法不對(duì),我們采用事件綁定的形式來(lái)解決這個(gè)問(wèn)題
// 綁定事件函數(shù) function lQbind(obj,eventName,fn){ // 標(biāo)準(zhǔn)瀏覽器 if(obj.addEventListener){ obj.addEventListener(eventName,fn,false); }else{ // IE瀏覽器 obj.attachEvent('on'+eventName,fn); } }
可以使用這樣調(diào)用
switch( typeof lArg){ case 'function': // 如果采用這種寫(xiě)法,給lQ綁定相同的函數(shù),但是只會(huì)執(zhí)行一次 // window.onload = lArg; // break; lQbind(window,'load',lArg); break; }
仿寫(xiě)jQuery中的$('.div')、$('#div')、$('div')三種方法
這三種方法的區(qū)別是第一個(gè)字符的不同,所以我們可以根據(jù)第一個(gè)字符的不同來(lái)進(jìn)行區(qū)別對(duì)待
先來(lái)仿寫(xiě)$('.div')
// '.div' case '.': this.elements = getClass(document,lArg.substring(1)); break;
由于getElementsByClassName()是HTML5里的方法,像IE8以下不兼容所以我們自己寫(xiě)了一個(gè)簡(jiǎn)單的getClass方法
// 獲取class屬性 function getClass(obj,name){ var arr = []; var elems = obj.getElementsByTagName('*'); for(var i=0;i<elems.length;i++){ if(elems[i].className == name){ arr.push(elems[i]); } } return arr; }
仿寫(xiě)$('#div')
case '#': this.elements.push(document.getElementById(lArg.substring(1))); break; // '.div' case '.':
仿寫(xiě)$('div')
default: // getElementsByTagName返回的是一個(gè)類(lèi)數(shù)組NodeList,為了防止以后出現(xiàn)麻煩,要把他轉(zhuǎn)為一個(gè) // 數(shù)組 this.elements = toArray(document.getElementsByTagName(lArg)); break;
由于getElementsByTagName返回的是一個(gè)類(lèi)數(shù)組NodeList,為了防止以后出現(xiàn)麻煩,要把他轉(zhuǎn)為一個(gè)數(shù)組,自定義了一個(gè)toArray方法
// 將一個(gè)類(lèi)數(shù)組轉(zhuǎn)為真正的數(shù)組 function toArray(lickArr){ var arr = []; for(var i=0;i<lickArr.length;i++){ arr.push(lickArr[i]); } return arr; }
仿寫(xiě)$(對(duì)象)的方法
// window document
case 'object':
this.elements.push(lArg);
break;
html()的實(shí)現(xiàn)
html()方法分為有參和無(wú)參
// html()方法 lQuery.prototype.html = function(str){ if(str){ //設(shè)置 for(var i=0;i<this.elements.length;i++){ this.elements[i].innerHTML = str; } }else{ return this.elements[0].innerHTML; } return this; };
on()方法的實(shí)現(xiàn)
利用前面實(shí)現(xiàn)的綁定函數(shù)可以很容易的實(shí)現(xiàn)
lQuery.prototype.on = function(eventName,fn){
for(var i=0;i<this.elements.length;i++){
lQbind(this.elements[i],eventName,fn);
}
}
click()和mouseover()方法的實(shí)現(xiàn)
利用on()方法可以容易的實(shí)現(xiàn)
// click()方法 lQuery.prototype.click = function(fn){ this.on('click',fn); return this; } // mouseover()方法 lQuery.prototype.mouseover = function(fn){ this.on('mouseover',fn); return this; }
hide()和show()方法的實(shí)現(xiàn)
// hide()方法 lQuery.prototype.hide = function(){ for(var i=0;i<this.elements.length;i++){ this.elements[i].style.display = 'none'; } return this; } // show()方法 lQuery.prototype.show = function(){ for(var i=0;i<this.elements.length;i++){ this.elements[i].style.display = 'block'; } return this; }
hover()方法的實(shí)現(xiàn)
// hover()方法 lQuery.prototype.hover = function(fnover,fnout){ this.on('mouseover',fnover); this.on('mouseout',fnout); return this; }
css()方法的實(shí)現(xiàn)
實(shí)現(xiàn)$('div').css('width')和$('div').css('width','200px')
lQuery.prototype.css = function(attr,value){ if(arguments.length == 2){ for(var i=0;i<this.elements.length;i++){ this.elements[i].attr = value; } } if(arguments.length == 1){ return getStyle(this.elements[0],attr); } }
定義了getStyle()方法是為了能找到行內(nèi)樣式以外的樣式
// 獲取屬性 function getStyle(obj,attr){ if(obj.currentStyle[attr]){ obj.currentStyle[attr]; }else{ obj.getComputedStyle(obj,false)[attr]; } }
attr()方法的實(shí)現(xiàn)
用了和css()不同的方法
// attr()方法 lquery.prototype.attr = function(attr,value){ if(arguments.length == 2){ //設(shè)置 for(var i=0;i<this.elements.length;i++){ this.elements[i].setAttribute(attr,value); } } else if(arguments.length == 1){ //獲取 return this.elements[0].getAttribute(attr); } return this; };
eq()方法的實(shí)現(xiàn)
實(shí)現(xiàn)$('div').eq(1)
由于eq()方法返回的對(duì)象要操作許多l(xiāng)Query的方法,所以返回的對(duì)象必須是lQuery對(duì)象
lQuery.prototype.eq = function(num){ return lQ(this.elements[num]); };
index()方法的實(shí)現(xiàn)
實(shí)現(xiàn)$('div').index() 返回這個(gè)元素在同輩元素中的位置
lQuery.prototype.index = function(){ var elems = this.elements[0].parentNode.children; for(var i=0;i<elems.length;i++){ if( elems[i] == this.elements[0] ){ return i; } } };
阻止默認(rèn)事件和阻止事件冒泡
在jQuery中 return false 是阻止默認(rèn)事件和事件冒泡,所以我們要對(duì)lQbind函數(shù)進(jìn)行修改,通過(guò)判斷綁定的函數(shù)的返回值是否為false來(lái)判斷是否要進(jìn)行阻止默認(rèn)事件和阻止事件冒泡
function lQbind(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; return false; } }); } }
find()方法的實(shí)現(xiàn)
仿寫(xiě)$('div').find('.box')和$('div').find('#box')方法
這里涉及到通過(guò)判斷find()參數(shù)第一個(gè)字符的方法來(lái)進(jìn)行不同的操作和$()方法差不多,在循環(huán)時(shí)要使用concat()方法來(lái)連接數(shù)組,最后返回一個(gè)lQuery對(duì)象
lQuery.prototype.find = function(sel){ var arr = []; if( sel.charAt(0) == '.' ){ for(var i=0;i<this.elements.length;i++){ arr = arr.concat(getClass( this.elements[i] , sel.substring(1) )); } } else{ for(var i=0;i<this.elements.length;i++){ arr = arr.concat(toArray(this.elements[i].getElementsByTagName(sel))); } } return lQ(arr); };
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
- jQuery實(shí)現(xiàn)隔行變色的方法分析(對(duì)比原生JS)
- 原生js仿jquery實(shí)現(xiàn)對(duì)Ajax的封裝
- 原生JS取代一些JQuery方法的簡(jiǎn)單實(shí)現(xiàn)
- 原生js仿jquery一些常用方法(必看篇)
- 原生js封裝的一些jquery方法(詳解)
- 原生js實(shí)現(xiàn)jquery函數(shù)animate()動(dòng)畫(huà)效果的簡(jiǎn)單實(shí)例
- 原生js仿jquery animate動(dòng)畫(huà)效果
- 原生js和jquery分別實(shí)現(xiàn)橫向?qū)Ш讲藛涡Ч?/a>
- 原生JS和jQuery版實(shí)現(xiàn)文件上傳功能
- 使用jQuery或者原生js實(shí)現(xiàn)鼠標(biāo)滾動(dòng)加載頁(yè)面新數(shù)據(jù)
- 原生js和jQuery實(shí)現(xiàn)淡入淡出輪播效果
- 原生js與jQuery實(shí)現(xiàn)簡(jiǎn)單的tab切換特效對(duì)比
相關(guān)文章
如何使用big.js解決JavaScript浮點(diǎn)數(shù)精度丟失問(wèn)題
最近在項(xiàng)目中涉及到金額從元轉(zhuǎn)為分(乘100即可),發(fā)現(xiàn)乘法居然也會(huì)有精度丟失的問(wèn)題,關(guān)于浮點(diǎn)數(shù)計(jì)算精度丟失是很多語(yǔ)言都存在的問(wèn)題,本文給大家分享使用big.js解決JavaScript浮點(diǎn)數(shù)精度丟失問(wèn)題,感興趣的朋友一起看看吧2023-12-12跟我學(xué)習(xí)javascript的var預(yù)解析與函數(shù)聲明提升
跟我學(xué)習(xí)javascript的var預(yù)解析與函數(shù)聲明提升,小編對(duì)var預(yù)解析與函數(shù)聲明提升知識(shí)點(diǎn)也不甚了解,和大家一起學(xué)習(xí)本篇文章。2015-11-11Eclipse去除js(JavaScript)驗(yàn)證錯(cuò)誤
這篇文章主要是對(duì)Eclipse去除js(JavaScript)驗(yàn)證錯(cuò)誤進(jìn)行了介紹。在Eclipse中,js文件常常會(huì)報(bào)錯(cuò)??梢酝ㄟ^(guò)如下幾個(gè)步驟解決2014-02-02js實(shí)現(xiàn)多選項(xiàng)切換導(dǎo)航菜單的方法
這篇文章主要介紹了js實(shí)現(xiàn)多選項(xiàng)切換導(dǎo)航菜單的方法,可實(shí)現(xiàn)動(dòng)態(tài)生成多選項(xiàng)切換導(dǎo)航菜單的功能,是非常實(shí)用的技巧,需要的朋友可以參考下2015-02-02JavaScript文件的同步和異步加載的實(shí)現(xiàn)代碼
本篇文章主要介紹了JavaScript文件的同步和異步加載的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08js的window.showModalDialog及window.open用法實(shí)例分析
這篇文章主要介紹了js的window.showModalDialog及window.open用法,實(shí)例分析了window.showModalDialog與window.open方法的定義、功能與使用技巧,需要的朋友可以參考下2015-01-01使用Javascript簡(jiǎn)單實(shí)現(xiàn)圖片無(wú)縫滾動(dòng)
本文簡(jiǎn)單介紹了使用原生javascript實(shí)現(xiàn)簡(jiǎn)單的圖片無(wú)縫滾動(dòng)的方法,并附上示例代碼,推薦給大家,直接可以用在項(xiàng)目中的。2014-12-12