JQuery極大的提高了我們編寫JavaScript的效率,讓我們可以愉快的編寫代碼,做出各種特效。大多數情況下,我們都是使用別人開發的JQuery插件,今天我們就來看看如何把我們常用的功能做出JQuery插件,然後像使用jQuery那樣來操作DOM. 一、jQuery插件開發快速上手 1、jQue ...
JQuery極大的提高了我們編寫JavaScript的效率,讓我們可以愉快的編寫代碼,做出各種特效。大多數情況下,我們都是使用別人開發的JQuery插件,今天我們就來看看如何把我們常用的功能做出JQuery插件,然後像使用jQuery那樣來操作DOM.
一、jQuery插件開發快速上手1、jQuery插件模板
關於jQuery插件的編寫,我們可以通過為jQuery.fn增加一個新的函數來編寫jQuery插件。屬性的名字就是你的插件的名字,其模板如下:
(function($){
$.fn.myJQPlugin = function(){
//TODO:add your code
}
})(jQuery);
其中myJQPlugin 就是你插件的名字,Function裡面的代碼就是你插件的功能實現代碼。
2、與DOM交互
給插件起好名字後,下麵就可以編寫我們的代碼了,但是編寫之前,必須要說一說上下文。在插件內部的範圍中,this關鍵字指向的是jQuery對象。人們很容易誤解這一點,因為在正常使用jQuery的時候,this通常指向的是一個DOM元素。不瞭解這一點,會經常使用$又包裝了一次。
(function( $ ){
$.fn.myJQPlugin = function() {
// 沒有必要使用$(this)
// $(this) 跟 $($('#element'))是一樣的
this.html("Hello,world");
this.click(function(){
this.hide(); //註意這裡的this不再指向jQuery元素,這裡的this指向當前這個function對象
});
};
})( jQuery );
這裡又要提到this的指向問題,比如我們想實現一個功能,點擊DOM元素,隱藏當前元素,雖然說this指向的是jQuery對象,但是在click中,this的指向發生了變化,指向了它所在的function.所以我們在click方法裡面訪問當前元素,就要通過變數了,實現方法如下:
(function( $ ){
$.fn.myJQPlugin = function() {
// 沒有必要使用$(this)
// $(this) 跟 $($('#element'))是一樣的
this.html("Hello,world");
var $this = $(this);
this.click(function(){
$this.hide(); //註意這裡的this不再指向jQuery元素,這裡的this指向當前這個function對象
});
};
})( jQuery );
我們聲明$this變數來保存this對象,這樣我們需要使用當前元素時,直接使用$this就可以了。下麵我們通過一個完整的實例來測試一下:
其中html頁面的代碼如下:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="jquery.js" type="text/javascript"></script>
<script src="1.js" type="text/javascript"></script>
</head>
<body>
<div id="container" style="width:800px;height:200px; border:2px #000 solid;padding:20px;font-size:20px;">Hello,world</div>
</body>
<script type="text/javascript">
$('#container').myJQPlugin();
</script>
</html>
jQuery插件的js代碼如下:
(function($){
$.fn.myJQPlugin = function(){
this.css("color","red"); //字體顏色為紅色
this.hide();
this.slideDown(200); //先隱藏,然後通過slideDown顯示出來
var $this = $(this);
this.click(function(){
$this.html("Thanks,good bye!"); //顯示信息,然後淡出
$this.fadeOut(2000);
});
}
})(jQuery);
這個插件的功能就是首先讓元素下拉顯示,然後點擊元素時顯示再見信息,然後經過2s後淡出。這裡大家可以試試在click事件裡面使用this會怎麼樣。
二、jQuery的鏈式操作
1、為什麼要用鏈式操作?
實際上鏈式操作僅僅是通過對象上的方法最後加上return this. 把對象再返回回來,對象當然可以繼續調用方法啦,所以就可以鏈式操作了。那麼,簡單實現一個:
按 Ctrl+C 複製代碼 按 Ctrl+C 複製代碼
一般的解釋:
節省代碼量,代碼看起來更優雅。例如如果沒有鏈式,那麼你可能需要這樣寫代碼:
document.getElementById("ele").dosomething();
document.getElementById("ele").dootherthing();
這個代碼中調用了兩次document.getElementById來獲取DOM樹的元素,這樣消耗比較大,而且要寫兩行,而鏈式只要寫一行,節省了代碼……
但我們也可以用緩存元素啊。比如:
var ele = document.getElementById("ele");
ele.dosomething();
ele.dootherthing();
而且兩行並沒有比一行多多少代碼,甚至相應的封裝反而使得代碼更多了。
最糟糕的是所有對象的方法返回的都是對象本身,也就是說沒有返回值,這不一定在任何環境下都適合。
2、那麼到底為什麼要用鏈式操作呢?
為了更好的非同步體驗Javascript是無阻塞語言,所以他不是沒阻塞,而是不能阻塞,所以他需要通過事件來驅動,非同步來完成一些本需要阻塞進程的操作。
但是非同步編程是一種令人瘋狂的東西……運行時候是分離的倒不要緊,但是編寫代碼時候也是分離的就……
常見的非同步編程模型有哪些呢?
(1)回調函數 :
所謂的回調函數,意指先在系統的某個地方對函數進行註冊,讓系統知道這個函數的存在,然後在以後,當某個事件發生時,再調用這個函數對事件進行響應。
function fun(num, callback){
if(num < 0) {
alert("分數不能為負,輸入錯誤!");
}else if(num == 0){
alert("該學生可能未參加考試!");
}else {
alert("調用高層函數處理!");
setTimeout(function(){callback();}, 1000);
}
}
這裡callback則是回調函數。可以發現只有當num為非負數時候callback才會調用。
但是問題,如果我們不看函數內部,我們並不知道callback會幾時調用,在什麼情況下調用,代碼間產生了一定耦合,流程上也會產生一定的混亂。
雖然回調函數是一種簡單而易於部署的實現非同步的方法,但從編程體驗來說它卻不夠好。
(2)鏈式非同步 :
個人覺得鏈式操作最值得稱贊的還是其解決了非同步編程模型的執行流程不清晰的問題。jQuery中$(document).ready就非常好的闡釋了這一理念。DOMContentLoaded是一個事件,在DOM並未載入前,jQuery的大部分操作都不會奏效,但jQuery的設計者並沒有把他當成事件一樣來處理,而是轉成一種“選其對象,對其操作”的思路。$選擇了document對象,ready是其方法進行操作。這樣子流程問題就非常清晰了,在鏈條越後位置的方法就越後執行。
(function(){
var isReady=false; //判斷onDOMReady方法是否已經被執行過
var readyList= [];//把需要執行的方法先暫存在這個數組裡
var timer;//定時器句柄
ready=function(fn) {
if (isReady )
fn.call( document);
else
readyList.push( function() { return fn.call(this);});
return this;
}
var onDOMReady=function(){
for(var i=0;i<readyList.length;i++){
readyList[i].apply(document);
}
readyList = null;
}
var bindReady = function(evt){
if(isReady) return;
isReady=true;
onDOMReady.call(window);
if(document.removeEventListener){
document.removeEventListener("DOMContentLoaded", bindReady, false);
} else if(document.attachEvent){
document.detachEvent("onreadystatechange", bindReady);
if(window == window.top){
clearInterval(timer);
timer = null;
}
}
};
if(document.addEventListener){
document.addEventListener("DOMContentLoaded", bindReady, false);
}else if(document.attachEvent){
document.attachEvent("onreadystatechange", function(){
if((/loaded|complete/).test(document.readyState))
bindReady();
});
if(window == window.top){
timer = setInterval(function(){
try{
isReady||document.documentElement.doScroll('left');//在IE下用能否執行doScroll判斷dom是否載入完畢
}
catch(e){
return;
}
bindReady();
},5);
}
}
})();
上面的代碼不能用$(document).ready,而應該是window.ready。
(3)Promise :
CommonJS中的非同步編程模型也延續了這一想法,每一個非同步任務返回一個Promise對象,該對象有一個then方法,允許指定回調函數。
所以我們可以這樣寫:
f1().then(f2).then(f3);
這種方法我們無需太過關註實現,也不太需要理解非同步,只要懂得通過函數選對象,通過then進行操作,就能進行非同步編程。
三、維護鏈式開發的特性
在jQuery中,一個插件緊緊是修改收集到的元素,然後返回這個元素讓鏈條上的下一個使用。這是jQuery設計的精美之處,也是jQuery如此流行的原因之一。為了保證可鏈式,你必須返回this。如下代碼:
(function( $ ){
$.fn.resize = function( type, value ) {
return this.each(function() {
var $this = $(this);
if (!type || type == 'width' ) {
$this.width(value);
}
if ( !type || type == 'height' ) {
$this.height(value);
}
});
};
})(jQuery);
調用方法如下:
$('div').resize('width', '600').css('color','blue');
四、jQuery插件編寫總結
編寫jQuery插件可以充分利用庫,將公用的函數抽象出來,“迴圈利用”。以下是簡短的總結:
- 使用(function($){//plugin})(jQuery);來包裝你的插件
- 不要在插件的初始範圍中重覆包裹
- 除非你返回原始值,否則返回this指針來保證可鏈式
- 不要用一串參數,而是使用一個對象,並且設置預設值
- 一個插件,不要為jQuery.fn附上多個函數
- 為你的函數,事件,數據附著到某個命名空間
五、參考資料
jQuery插件開發 http://www.cnblogs.com/playerlife/archive/2012/05/11/2495269.html
jQuery鏈式操作如何實現以及為什麼要用鏈式操作 http://www.jb51.net/article/33342.htm
轉自:http://www.cnblogs.com/yunfeifei/