jQuery的插件开发主要分为两类:
1. 类级别,即在jQuery类本身上扩展方法,类似与 $.ajax,$.get 等。
2. 对象级别,这里所谓的对象是指通过jQuery选择器选中的jQuery对象,在该对象上添加方法。例如:$('div').css(), $('div').show() 等。
在实际开发中,我们通常选用对象级别的方法来开发插件,jQuery强大的选择器及对象操作是我们选择这种方式很大的一个原因。
接下来我们看看两种方式的具体写法是什么:
类级别的插件开发
$.extend({ foo: function() { //... }, bar: function() { //... } }) //调用 $.foo();
在这里,对扩展方法的命名需要考究一些,以免与jQuery类中的原有方法重名。即便如此,当我们需要在类上扩展多个方法时仍有可能会出现命名冲突的情况,为此我们可以创建自定义的命名空间:
$.myPlugin = { foo: function() { //... }, bar: function() { //... } } //调用 $.myPulgin.foo();
对象级别的插件开发
$.fn.foo = function() { //doSomething... } //调用(假设拥有一个id为obj的元素) $('#obj').foo(); 有个会问 fn 是什么东东?粘一段别人截取的jQuery源码就明白了: jQuery.fn = jQuery.prototype = { init: function(selector, context) { //.... } }
原来是原型链啊。。。
接收配置参数
在编写一个插件时,我们可以让使用插件的人能按自己的意愿设置插件的一些属性,这就需要插件有接收参数的功能,同时当使用插件的人不传入参数时,插件内部也有一套自己默认的配置参数。
$.fn.foo = function(options) { var defaults = { color: '#000', backgroundColor: 'red' }; var opts = $.extend({}, defaults, options); alert(opts.backgroundColor); //yellow } $('#obj').foo({ backgroundColor: 'yellow' })
这里的关键就是 $.extend 方法,它能够将对象进行合并。对于相同的属性,后面的对象会覆盖前面的对象。为什么extend方法第一个参数是一个空对象呢?因为该方法会将后者合并到前者上,为了不让 defaults 被改变所以第一个参数设为空对象。
如果我们允许使用插件的人能够设置默认参数,就需要将其暴露出来:
$.fn.foo = function(options) { var opts = $.extend({}, $.fn.foo.defaults, options); alert(opts.backgroundColor); } $.fn.foo.defaults = { color: '#000', backgroundColor: 'red' }
这样就可以在外部对插件的默认参数进行修改了。
适当的暴露一些方法
$.fn.foo = function(options) { var opts = $.extend({}, $.fn.foo.defaults, options); $.fn.foo.sayColor(opts.backgroundColor); } $.fn.foo.sayColor = function(bgColor) { alert(bgColor); } $.fn.foo.defaults = { color: '#000', backgroundColor: 'red' }
改写:
$.fn.foo.sayColor = function(bgColor) { alert('background color is ' + bgColor); }
暴露插件中的一部分方法是很牛逼的,它使得别人可以对你的方法进行扩展、覆盖。但是当别人对你的参数或方法进行修改时,很可能会影响其他很多东西。所以在考虑要不要暴露方法时候要头脑清楚,不确定的就不要暴露了。
保持函数的私有性
说到保持私有性,首先想到什么?没错,就是闭包:
;(function($) { $.fn.foo = function(options) { var opts = $.extend({}, $.fn.foo.defaults, options); debug(opts.backgroundColor); } function debug(bgColors) { console.log(bgColors); } $.fn.foo.defaults = { color: '#000', backgroundColor: 'red' } })(jQuery)
这是jQuery官方给出的插件开发方式,好处包括:1.没有全局依赖 2.避免其他人破坏 3.兼容 '$' 与 'jQuery' 操作符。
如上,debug 方法就成了插件内部的私有方法,外部无法对其进行修改。在闭包前面加 ; 是防止进行代码合并时,如果闭包前的代码缺少分号从而导致后面报错的情况。
合并
;(function($) { //定义插件 $.fn.foo = function(options) { //doSomething... } //私有函数 function debug() { //doSomething... } //定义暴露函数 $.fn.foo.sayColor = function() { //doSomething... } //插件默认参数 $.fn.foo.default = { color: '#000', backgroundColor: 'red' } })(jQuery);
以上的代码就创建了一个完整且规范的插件骨架,看起来虽然很简单但在实际开发中还是有很多技巧与注意事项,接下来我们通过一个实例来看看。
想了半天,觉得将弹窗做成插件当作示例是比较合适的。在开发之前我们先构想一下这个弹窗插件的结构与功能等:
从上图我们看出包括三个部分,标题、内容、以及按钮组。这里需要申明一点,我们不想只做成浏览器里默认的只包含一个按钮的alert框,而是使用者可以自定义按钮数量,这样该弹出框也能完成类似confirm框的功能。
搭建插件骨架