学习 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 官方网站的插件教程中总结出来的: