學習 JQuery 插件開發以後, 能夠將本身平時經常使用的功能封裝成插件, 便於在不一樣的項目之間使用.javascript
JQuery 官網上的 插件開發教程就很不錯, 簡單易懂.css
參考網址:html
本文就是基於官網上的教程整理的, 也加入了本身實驗的一些示例。java
jquery 中有2個重要的API是和插件編寫相關的.jquery
這2個API都是爲了將本身編寫的功能以插件的形式加入到 jquery 中.chrome
可是含義上是有區別的.json
這個函數是用來擴展 jQuery 自己, 也就是擴展 "$" 的.閉包
示例以下:函數
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript"> $(function(){ $("#btn-extend").click(function(){ $.extend({ test: function(a) { alert(a); }, }); }); $("#btn-test").click(function(){ if ($.test) $.test("test"); else alert("不存在 $.test 方法!"); }); }); </script> </head> <body> <button id="btn-test">測試 $.test() </button> <button id="btn-extend">擴展 $ 自己 </button> </body> </html>
首先點擊 [btn-test] 按鈕, 提示沒有 test 方法, 而後點擊 [btn-extend] 按鈕, 擴展 $ 自己.學習
再次點擊 [btn-test] 按鈕, 執行擴展的 $.test() 函數.
這個函數用來爲 jQuery 對象提供新的方法.
所謂 jQuery 對象, 最多見的咱們平時經過jQuery選擇器獲取的對象, 好比: $("#id"), $(".class") 等等.
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript"> $(function(){ $("#btn-extend").click(function(){ $.fn.extend({ test: function(a) { alert(a); }, }); }); $("#btn-test").click(function(){ if ($(this).test) $(this).test($(this).attr("id")); else alert("不存在 test 方法!"); }); }); </script> </head> <body> <button id="btn-test">測試 $(this).test() </button> <button id="btn-extend">擴展 jQuery($) 對象 </button> </body> </html>
首先點擊 [btn-test] 按鈕, 提示沒有 test 方法, 而後點擊 [btn-extend] 按鈕, 擴展 $ 對象.
再次點擊 [btn-test] 按鈕, 執行擴展的 $.fn.test() 函數.
編寫 jQuery 插件以前, 必定要弄懂 "$ 自己" 和 "$ 對象" 的區別. ($ 就是 jQuery)
也就是弄懂 $.extend 和 $.fn.extend 之間的區別.
通常來講, 純UI相關的插件不多, 都是UI和功能一塊兒配合使用的, 好比 jQuery UI 庫.
下面的示例主要爲了說明如何使用 jQuery 插件, 因此只和UI相關.
示例 HTML:
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript" src="js/jquery-plugin.js"></script> <script type="text/javascript"> $(function(){ $("#btn-plugin").click(function(){ $(".smalldiv").toggle_back(); }); }); </script> <style type="text/css" media="screen"> .bigdiv { width: 500px; height:100px; } .smalldiv { width: 50px; height: 50px; background-color: green; float:left; } </style> </head> <body> <button id="btn-plugin">執行插件</button> <div class="bigdiv"> <div class="smalldiv red"> 1 </div> <div class="smalldiv green"> 2 </div> <div class="smalldiv red"> 3 </div> <div class="smalldiv green"> 4 </div> <div class="smalldiv red"> 5 </div> <div class="smalldiv green"> 6 </div> <div class="smalldiv red"> 7 </div> <div class="smalldiv green"> 8 </div> <div class="smalldiv red"> 9 </div> <div class="smalldiv green"> 10 </div> </div> </body> </html>
示例 jQuery 插件:
/* jquery plugin for test * filename: jquery-plugin.js */ // 下面的格式也是 jQuery 插件的經常使用寫法 (function ($) { $.fn.toggle_back = function() { if (this.css("background-color") == "rgb(255, 0, 0)") this.css("background-color", "green"); else this.css("background-color", "red"); }; }(jQuery));
經過點擊 html 頁面上的按鈕, 能夠切換全部 smalldiv 的背景色.
這個例子比上面那個略微複雜一些, 上面的示例1 是對全部 smalldiv 統一設置背景色, 不夠靈活.
這個示例經過 jQuery 的 $.fn.each 函數根據每一個 smalldiv 的 class 分別設置背景色.
(HTML部分的代碼和示例1 同樣)
/* jquery plugin for test * filename: jquery-plugin.js */ // 下面的格式也是 jQuery 插件的經常使用寫法 (function ($) { $.fn.toggle_back = function() { this.each(function() { var div = $(this); if (div.hasClass("red")) { div.removeClass("red"); div.addClass("green"); div.css("background-color", "green"); } else { div.removeClass("green"); div.addClass("red"); div.css("background-color", "red"); } }); return this; }; }(jQuery));
這裏須要注意2個地方:
1. 代碼中 this 的含義
this.each(function() {
這裏的 this 是jQuery 對象, 也就是經過 $("#id"), $(".class") 之類的選擇器獲取的對象.
*注意* 這個 this 的位置是在 $.fn.toggle_back 的主函數體中.
var div = $(this);
這裏的 this 是 DOM 對象, 因此經過 $(this) 才能變成 jQuery 對象.
至於爲何 each 中的this就是各個 DOM 對象, 那是由於 each 的實現中將 jQuery 對象轉換爲了 DOM 對象.
2. 插件代碼最後的 return this;
這裏之因此要 return this; 是爲了實現 jQuery 的鏈式表達式. 也就是 return this; 以後, 能夠接着調用其餘 jQuery 函數.
好比 $(".class").toggle_back().css("color", "red");
上面的示例2中 $("#btn-plugin").click 函數能夠改成以下:
$("#btn-plugin").click(function(){ $(".smalldiv").toggle_back().css("color", "red"); });
下面經過一個 日期轉換 的例子, 說明功能型插件的寫法.
HTML 部分:
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript" src="js/jquery-plugin.js"></script> <script type="text/javascript"> $(function(){ $("#btn-plugin").click(function(){ $("h2").dt_format(new Date()); }); }); </script> </head> <body> <button id="btn-plugin">顯示格式化的時間</button> <hr /> <h1>當前時間:</h1> <h2 class="date">nothing</h2> <h2 class="time">nothing</h2> <h2 class="datetime">nothing</h2> </body> </html>
插件 js 只是簡單的轉換了一時間格式, 僅僅爲了演示:
/* jquery plugin for test * filename: jquery-plugin.js */ (function ($) { $.fn.dt_format = function(dt) { this.each(function(){ var elem = $(this); if (elem.hasClass("date")) elem.text($.fn.dt_format.date(dt)); if (elem.hasClass("time")) elem.text($.fn.dt_format.time(dt)); if (elem.hasClass("datetime")) elem.text($.fn.dt_format.datetime(dt)); }); return this; }; $.fn.dt_format.date = function(dt) { var year = dt.getFullYear(); var month = dt.getMonth() + 1; var day = dt.getDate(); return year + "年/" + month + "月/" + day + "日"; }; $.fn.dt_format.time = function(dt) { var hour = dt.getHours(); var minute = dt.getMinutes(); var second = dt.getSeconds(); return hour + "時:" + minute + "分:" + second + "秒"; }; $.fn.dt_format.datetime = function(dt) { return $.fn.dt_format.date(dt) + " " + $.fn.dt_format.time(dt); }; }(jQuery));
點擊HTML頁面上的按鈕, 分別轉換出不一樣的時間格式並顯示在頁面上.
上面的插件須要一個參數, 若是調用插件時沒有帶參數, 則致使js錯誤.
爲了更好的用戶體驗, 下面給插件加入默認參數(也就是當前時間).
新的 plugin js以下:
/* jquery plugin for test * filename: jquery-plugin.js */ (function ($) { $.fn.dt_format = function(options) { // 將用戶的options 和 默認參數defaults 合併, 若有重複, 優先使用 options // 這裏的 $.extend 的第一個參數是空的對象, 緣由後面解釋 var settings = $.extend({}, $.fn.dt_format.defaults, options); this.each(function(){ var elem = $(this); if (elem.hasClass("date")) elem.text($.fn.dt_format.date(settings.dt)); if (elem.hasClass("time")) elem.text($.fn.dt_format.time(settings.dt)); if (elem.hasClass("datetime")) elem.text($.fn.dt_format.datetime(settings.dt)); }); return this; }; // 這裏提供默認參數 $.fn.dt_format.defaults = { dt: new Date(), }; $.fn.dt_format.date = function(dt) { var year = dt.getFullYear(); var month = dt.getMonth() + 1; var day = dt.getDate(); return year + "年/" + month + "月/" + day + "日"; }; $.fn.dt_format.time = function(dt) { var hour = dt.getHours(); var minute = dt.getMinutes(); var second = dt.getSeconds(); return hour + "時:" + minute + "分:" + second + "秒"; }; $.fn.dt_format.datetime = function(dt) { return $.fn.dt_format.date(dt) + " " + $.fn.dt_format.time(dt); }; }(jQuery));
HTML中調用插件時能夠不用參數了
$(function(){ $("#btn-plugin").click(function(){ $("h2").dt_format(); // 這裏能夠不輸入參數, 使用默認參數. }); });
補充: 合併參數時, 使用了 $.extend, 這個方法的做用是將全部參數 合併成一個大的json對象, 有相同的key時, 後面的參數覆蓋前面的參數.
$.extend 的第一個參數是 {}, 之因此這樣, 是由於合併後, 會破壞第一個參數, 因此不能將 defaults 放在第一個.
說明示例以下: (用chrome的console窗口能夠看到輸出結果)
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript"> $(function(){ var defaults = { "id": 1, "name": "test"}; var options = { "sex": "man", "name": "test2" }; console.log("合併前, 各個參數以下:"); console.log(defaults); console.log(options); console.log("合併後, 各個參數以下:"); $.extend(defaults, options); console.log(defaults); // 這裏能夠發現 defaults中的內容是 defaults和options合併後的結果 console.log(options); }); </script> </head> <body> </body> </html>
雖然 javascript 不是純粹的面向對象的語言, 可是經過其強大的閉包功能, 也能構造出相似其餘面嚮對象語言的公有/私有函數.
*功能型插件* 中的示例中3個函數 $.fn.dt_format.date, $.fn.dt_format.time, $.fn.dt_format.datetime 都是公有函數, 能夠被插件使用者所覆蓋.
好比, 將上面示例的HTML改成以下: (覆蓋了插件中的 $.fn.dt_format.datetime 方法)
<!DOCTYPE HTML> <html> <head> <title>jquery plugin test</title> <script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript" src="js/jquery-plugin.js"></script> <script type="text/javascript"> $(function(){ $("#btn-plugin").click(function(){ $("h2").dt_format(); }); }); $.fn.dt_format.datetime = function(dt) { alert("覆蓋公有函數"); }; </script> </head> <body> <button id="btn-plugin">顯示格式化的時間</button> <hr /> <h1>當前時間:</h1> <h2 class="date">nothing</h2> <h2 class="time">nothing</h2> <h2 class="datetime">nothing</h2> </body> </html>
若是不想公開方法, 改變那3個函數定義方法便可:
/* jquery plugin for test * filename: jquery-plugin.js */ (function ($) { $.fn.dt_format = function(options) { var settings = $.extend({}, $.fn.dt_format.defaults, options); this.each(function(){ var elem = $(this); if (elem.hasClass("date")) elem.text(date(settings.dt)); if (elem.hasClass("time")) elem.text(time(settings.dt)); if (elem.hasClass("datetime")) elem.text(datetime(settings.dt)); }); return this; }; $.fn.dt_format.defaults = { dt: new Date(), }; var date = function(dt) { var year = dt.getFullYear(); var month = dt.getMonth() + 1; var day = dt.getDate(); return year + "年/" + month + "月/" + day + "日"; }; var time = function(dt) { var hour = dt.getHours(); var minute = dt.getMinutes(); var second = dt.getSeconds(); return hour + "時:" + minute + "分:" + second + "秒"; }; var datetime = function(dt) { return date(dt) + " " + time(dt); }; }(jQuery));
這樣, 插件使用者就不能覆蓋 date, time, datetime 方法了.
是從 jQuery 官方網站的插件教程中總結出來的: