簡易版jQuery
前面的話
雖然jQuery已經日漸式微,但它裡面的許多思想,如選擇器、鏈式調用、方法函數化、取賦值合體等,有的已經變成了標準,有的一直影響到現在。所以,jQuery是一個偉大的前端框架。前端世界日新月異,由於實在是沒有時間去精讀源碼,於是自己封裝一個簡易版本的jQuery,來梳理jQuery的核心思路
基本構架由於火柴的英文是match,應該將這個簡單框架稱為mQuery。使用面向對象的寫法來寫mQuery,構造函數是Mquery(),調用$()方法,將根據Mquery()構造函數,創建一個實例對象
//構造函數function Mquery(arg){}
function $(arg){ return new Mquery(arg);}
jquery幾大特徵:
1、通過$()選擇的元素都是一個集合,即使僅僅是一個元素
因此,創建一個elements屬性為一個數組,去接收穫取的元素
//構造函數function Mquery(arg){ //保存所選擇的元素 this.elements = [];}
2、鏈式調用
所以,原型函數要返回this,以實現鏈式調用的效果
$函數
$函數根據參數類型的不同,用途也不同
1、參數為函數時,則直接運行
$(function(){ console.log(1)})
2、參數為對象時,則把DOM對象轉換為$對象
$(document.body)
3、參數為字元串時,則根據字元串選擇出元素,並轉換為$對象
$("#box")
下面根據以上三個分類,來編寫Mquery構建函數
//事件綁定兼容寫法function _addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,function(e){ //如果事件函數中出現 return false;則阻止默認事件和阻止冒泡 if(typeof handler == "function" && handler() === false){ e.preventDefault(); e.cancelBubble = true; } },false); }else{ target.attachEvent("on"+type,function(event){ if(typeof handler == "function" && handler() === false){ event.cancelBubble = true; event.returnValue = false; } return handler.call(target,event); }); }}//將類數組轉換成數組function _toArray(arrayLike){ return Array.prototype.slice.call(arrayLike);}
//構造函數function Mquery(arg){ //保存所選擇的元素 this.elements = []; switch(typeof arg){ //當參數是函數時,如$(function(){})(),直接運行裡面的代碼 case "function": _addEvent(window,"load",arg); break; //當參數是字元串時,選擇元素 case "string": this.elements = _toArray(document.querySelectorAll(arg)); break; //當參數是DOM對象時,將DOM對象轉換為$對象 case "object": if(arg.constructor == Array){ this.elements = arg; }else{ this.elements.push(arg); } break; }}
HTML、CSS及特性設置
下面來介紹常用的HTML、CSS及特性設置
【HTML】
對於文本內容來說,一般地,有三種方法:html()、text()和val()。本文只實現最常用的html()方法
當html()方法沒有參數時,表示獲取內容;有一個參數時,表示設置內容
//HTML獲取與設置Mquery.prototype.html = function(str){ //設置 if(str){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].innerHTML = str; } //獲取 }else{ return this.elements[0].innerHTML; } return this;}
【CSS】
對於CSS來說,有兩種參數格式:一種是json格式,一種是字元串格式
當第一個參數為對象時,則判斷為json格式,否則為字元串格式
對於字元串格式來說,只有一個參數時,為獲取樣式,兩個參數時,為設置樣式
獲取樣式時,僅獲取當前集合中第0個元素的樣式;設置樣式時,則設置當前集合中所有元素的樣式
//獲取計算樣式兼容寫法function _getCSS(obj,style){ if(window.getComputedStyle){ return getComputedStyle(obj)[style]; } return obj.currentStyle[style];}
//CSS獲取與設置Mquery.prototype.css = function(attr,value){ //如果是對象的形式,以對象的形式設置 if(typeof attr == "object"){ for(var att in attr){ for(var j = 0; j < this.elements.length; j++){ this.elements[j].style[att] = attr[att]; } } //如果不是對象的形式 }else{ //設置 if(arguments.length == 2){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].style[attr] = value; } //獲取 }else if(arguments.length == 1){ return _getCSS(this.elements[0],attr) } } return this;}
【attr】
特性設置與獲取的思路與CSS類似,只是方法變成了setAttribute()和getAttribute()
//attr獲取與設置Mquery.prototype.attr = function(attr,value){ //如果是對象的形式 if(typeof attr == "object"){ for(var att in attr){ for(var j = 0; j < this.elements.length; j++){ this.elements[j].setAttribute(att,attr[att]); } } //如果不是對象的形式 }else{ //設置 if(arguments.length == 2){ 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;}
事件綁定
【on】
在jQuery中,最常用的事件綁定方法就是on方法。在on方法中要特別注意的是this的綁定,由於函數fn中的this實際上是window,所以應該將fn的this綁定到當前元素
//事件綁定Mquery.prototype.on = function(eventType,fn){ for(var i = 0; i < this.elements.length; i++){ _addEvent(this.elements[i],eventType,fn.bind(this.elements[i)); } return this;}
【click和hover】
click方法是一個簡寫方法
Mquery.prototype.click = function(fn){ this.on("click",fn); return this;}
hover方法是mouseover和mouseout的合成方法
Mquery.prototype.hover = function(fnOver,fnOut){ this.on("mouseover",fnOver); this.on("mouseout",fnOut); return this;}
【return false】
在jQuery中,使用return false可以同時阻止默認行為和阻止冒泡
//事件綁定兼容寫法function _addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,function(e){ //如果事件函數中出現 return false;則阻止默認事件和阻止冒泡 if(typeof handler == "function" && handler() === false){ e.preventDefault(); e.cancelBubble = true; } },false); }else{ target.attachEvent("on"+type,function(event){ if(typeof handler == "function" && handler() === false){ event.cancelBubble = true; event.returnValue = false; } return handler.call(target,event); }); }}
其他設置
jQuery的功能非常強大。下面選擇一些常用功能進行實現
【顯示隱藏】
//隱藏Mquery.prototype.hide = function(){ for(var i = 0; i < this.elements.length; i++){ //保存當前元素的display值 this.elements[i].displayValue = this.elements[i].style.display; this.elements[i].style.display = "none"; } return this;}//顯示Mquery.prototype.show = function(){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].style.display = this.elements[i].displayValue; //刪除保存的元素的display值 delete this.elements[i].displayValue; } return this;}
【插件設置】
$.extend = function(json){ for(var attr in json){ $[attr] = json[attr]; }};$.fn = {};$.fn.extend = function(json){ for(var attr in json){ Mquery.prototype[attr] = json[attr]; } };
【索引設置】
//根據索引選擇元素Mquery.prototype.eq = function(number){ return $(this.elements[number]);}//根據元素獲取索引Mquery.prototype.index = function(){ var elements = this.elements[0].parentNode.children; for(var i = 0; i < elements.length; i++){ if(elements[i] === this.elements[0]){ return i; } }}
【子級篩選】
//篩選出當前匹配的元素集合中每個元素的後代Mquery.prototype.find = function(str){ var arr = []; for(var i = 0; i < this.elements.length; i++){ Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str)); } return $(arr);}
完整源碼
下面是mQuery的完整源碼
//事件綁定兼容寫法function _addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,function(e){ //如果事件函數中出現 return false;則阻止默認事件和阻止冒泡 if(typeof handler == "function" && handler() === false){ e.preventDefault(); e.cancelBubble = true; } },false); }else{ target.attachEvent("on"+type,function(event){ if(typeof handler == "function" && handler() === false){ event.cancelBubble = true; event.returnValue = false; } return handler.call(target,event); }); }}//獲取計算樣式兼容寫法function _getCSS(obj,style){ if(window.getComputedStyle){ return getComputedStyle(obj)[style]; } return obj.currentStyle[style];}//將類數組轉換成數組function _toArray(arrayLike){ return Array.prototype.slice.call(arrayLike);}//構造函數function Mquery(arg){ //保存所選擇的元素 this.elements = []; switch(typeof arg){ //當參數是函數時,如$(function(){})(),直接運行裡面的代碼 case "function": _addEvent(window,"load",arg); break; //當參數是字元串時,選擇元素 case "string": this.elements = _toArray(document.querySelectorAll(arg)); break; //當參數是DOM對象時,將DOM對象轉換為$對象 case "object": if(arg.constructor == Array){ this.elements = arg; }else{ this.elements.push(arg); } break; }}//根據索引選擇元素Mquery.prototype.eq = function(number){ return $(this.elements[number]);}//根據元素獲取索引Mquery.prototype.index = function(){ var elements = this.elements[0].parentNode.children; for(var i = 0; i < elements.length; i++){ if(elements[i] === this.elements[0]){ return i; } }}//篩選出當前匹配的元素集合中每個元素的後代Mquery.prototype.find = function(str){ var arr = []; for(var i = 0; i < this.elements.length; i++){ Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str)); } return $(arr);}//CSS獲取與設置Mquery.prototype.css = function(attr,value){ //如果是對象的形式,以對象的形式設置 if(typeof attr == "object"){ for(var att in attr){ for(var j = 0; j < this.elements.length; j++){ this.elements[j].style[att] = attr[att]; } } //如果不是對象的形式 }else{ //設置 if(arguments.length == 2){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].style[attr] = value; } //獲取 }else if(arguments.length == 1){ return _getCSS(this.elements[0],attr) } } return this;}//attr獲取與設置Mquery.prototype.attr = function(attr,value){ //如果是對象的形式 if(typeof attr == "object"){ for(var att in attr){ for(var j = 0; j < this.elements.length; j++){ this.elements[j].setAttribute(att,attr[att]); } } //如果不是對象的形式 }else{ //設置 if(arguments.length == 2){ 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;}//HTML獲取與設置Mquery.prototype.html = function(str){ //設置 if(str){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].innerHTML = str; } //獲取 }else{ return this.elements[0].innerHTML; } return this;}//隱藏Mquery.prototype.hide = function(){ for(var i = 0; i < this.elements.length; i++){ //保存當前元素的display值 this.elements[i].displayValue = this.elements[i].style.display; this.elements[i].style.display = "none"; } return this;}//顯示Mquery.prototype.show = function(){ for(var i = 0; i < this.elements.length; i++){ this.elements[i].style.display = this.elements[i].displayValue; //刪除保存的元素的display值 delete this.elements[i].displayValue; } return this;}//事件綁定Mquery.prototype.on = function(eventType,fn){ for(var i = 0; i < this.elements.length; i++){ _addEvent(this.elements[i],eventType,fn.bind(this.elements[i])); } return this;}//click簡寫Mquery.prototype.click = function(fn){ this.on("click",fn); return this;}//滑鼠移入移出Mquery.prototype.hover = function(fnOver,fnOut){ this.on("mouseover",fnOver); this.on("mouseout",fnOut); return this;}$.extend = function(json){ for(var attr in json){ $[attr] = json[attr]; }};$.fn = {};$.fn.extend = function(json){ for(var attr in json){ Mquery.prototype[attr] = json[attr]; } };function $(arg){ return new Mquery(arg);}
實際應用
下面使用mQuery來實現一個簡單的效果
<style>div { width:60px; height:60px; margin:5px; float:left; }</style><span id="result"></span><div style="background-color:blue;"></div><div style="background-color:rgb(15,99,30);"></div><div style="background-color:#123456;"></div><div style="background-color:#f11;"></div><script src="mQuery.js"></script><script>$("div").click(function(){ $("#result").html("背景顏色是 " + $(this).css("background-color"));})</script>
點擊不同顏色的元素塊,將在右側顯示具體的顏色值
好的代碼像粥一樣,都是用時間熬出來的標籤: jQuery
小火柴的藍色理想 關注 - 116 粉絲 - 2042 +加關注 0 ? 上一篇:Vue命令行工具vue-cli
推薦閱讀:
※用jQuery完成表單驗證(2)驗證用戶ID
※細說JS的類型判斷
※jQuery-$
※利用jquery完成一些簡單視覺效果(預備篇)
TAG:jQuery |