1, 开始
可以通过为 jQuery.fn 增加一个新的函数来编写 jQuery 插件. 属性的名字就是你的插件的名字:
- jQuery.fn.myPlugin = function(){
- // 开始写你的代码吧!
- };
但是, 那惹人喜爱的美元符号 $ 哪里去了? 她就是 jQuery, 但是为了确保你的插件与其他使用 $ 的库不冲突, 最好使用一个立即执行的匿名函数, 这个匿名函数的参数是 jQuery, 这样其他的库就可以放心的使用 $ 符号了.
- (function( $ ){
- $.fn.myPlugin = function() {
- // 开始吧!
- };
- })( jQuery );
这样更好了就. 在闭包内, 可以放心的使用 $ 符号了~
2, 上下文
现在已经可以编写我们的代码了, 但是编写之前, 我必须说一说上下文. 在插件内部的范围中, this 关键字指向的是 jQuery 对象. 人们很容易误解这一点, 因为在正常使用 jQuery 的时候, this 通常指向的是一个 DOM 元素. 不了解这一点, 会经常使用 $ 又包装了一次.
- (function( $ ){
- $.fn.myPlugin = function() {
- // 没有必要使用 $(this)
- // $(this) 跟 $($('#element')) 是一样的
- this.fadeIn('normal', function(){
- // 这里的 this 指的就是一个 DOM 元素了
- });
- };
- })( jQuery );
- $('#element').myPlugin();
3, 基本开发
接下来写一个能用的插件吧.
- (function( $ ){
- $.fn.maxHeight = function() {
- var max = 0;
- this.each(function() {
- max = Math.max( max, $(this).height() );
- });
- return max;
- };
- })( jQuery );
- var tallest = $('div').maxHeight();
这是一个简单的插件, 通过调用 height() 返回页面上 height 最大的 div 的 height.
4, 维护链式开发的特性
上一个例子是返回了一个整数, 但是大多数情况下, 一个插件紧紧是修改收集到的元素, 然后返回这个元素让链条上的下一个使用. 这是 jQuery 设计的精美之处, 也是 jQuery 如此流行的原因之一. 为了保证可链式, 你必须返回 this.
- (function( $ ){
- $.fn.lockDimensions = function( type ) {
- return this.each(function() {
- var $this = $(this);
- if ( !type || type == 'width' ) {
- $this.width( $this.width() );
- }
- if ( !type || type == 'height' ) {
- $this.height( $this.height() );
- }
- });
- };
- })( jQuery );
- $('div').lockDimensions('width').CSS('color','red');
因为该插件返回了 this, 所以保证了可链式, 从而可以继续使用 jQuery 方法进行修改, 如 CSS(). 如果你的插件如果不是返回一个简单值, 你通常应该返回 this. 而且, 正如你可能想到的, 你传进去的参数也可以在你的插件中访问. 所以在这个例子中, 可以访问到 type.
5, 默认值和选项
为了一些复杂的, 可订制的插件, 最好提供一套默认值, 在被调用的时候扩展默认值. 这样, 调用函数的时候就不用传入一大堆参数, 而是传入需要被替换的参数. 你可以这样做:
- (function( $ ){
- $.fn.tooltip = function( options ) {
- var settings = {
- 'location' : 'top',
- 'background-color' : 'blue'
- };
- return this.each(function() {
- // 如果存在选项, 则合并之
- if ( options ) {
- $.extend( settings, options );
- }
- // 其他代码咯
- });
- };
- })( jQuery );
- $('div').tooltip({'location':'left'});
在这个例子中, 调用插件后, 默认的 location 会被替换城'left', 而 background-color 还是'blue'. 这样可以保证高度可配置性, 而不需要开发者定义所有可能的选项了.
6, 命名空间
正确的命名空间对于插件开发十分重要, 这样能确保你的插件不被其他插件重写, 也能避免被页面上其他代码重写. 命名空间可以使你更长寿, 因为你能记录你自己的方法, 事件, 数据等.
a, 插件方法
在任何情况下, 都不要在一个插件中为 jQuery.fn 增加多个方法. 如:
- (function( $ ){
- $.fn.tooltip = function( options ) { // 这样 };
- $.fn.tooltipShow = function( ) { // 是 };
- $.fn.tooltipHide = function( ) { // 不好的 };
- $.fn.tooltipUpdate = function( content ) { // 同学! };
- })( jQuery );
不推荐这样使用, 搞乱了 $.fn 命名空间. 要纠正之, 你可以把所有的方法放进一个对象中, 然后通过不同的参数来调用.
- (function( $ ){
- var methods = {
- init : function( options ) { // THIS },
- show : function( ) { // IS },
- hide : function( ) { // GOOD },
- update : function( content ) { // !!! }
- };
- $.fn.tooltip = function( method ) {
- // Method calling logic
- if ( methods[method] ) {
- return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
- } else if ( typeof method === 'object' || ! method ) {
- return methods.init.apply( this, arguments );
- } else {
- $.error( 'Method' + method + 'does not exist on jQuery.tooltip' );
- }
- };
- })( jQuery );
- $('div').tooltip({ // calls the init method
- foo : 'bar'
- });
- $('div').tooltip('hide'); // calls the hide method
- $('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method
jQuery 自己的扩展也是使用这种插件结构.
b, 事件
绑定事件的命名空间是比较不为人知的. 如果你的插件绑定了某个事件, 最好将它搞到一个命名空间中. 这样, 如果你以后需要解绑, 就不会影响到其他绑定到这个事件上的函数了. 你可以使用 ".
- (function( $ ){
- var methods = {
- init : function( options ) {
- return this.each(function(){
- $(Windows).bind('resize.tooltip', methods.reposition);
- });
- },
- destroy : function( ) {
- return this.each(function(){
- $(Windows).unbind('.tooltip');
- })
- },
- reposition : function( ) { // ... },
- show : function( ) { // ... },
- hide : function( ) { // ... },
- update : function( content ) { // ...}
- };
- $.fn.tooltip = function( method ) {
- if ( methods[method] ) {
- return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
- } else if ( typeof method === 'object' || ! method ) {
- return methods.init.apply( this, arguments );
- } else {
- $.error( 'Method' + method + 'does not exist on jQuery.tooltip' );
- }
- };
- })( jQuery );
- $('#fun').tooltip();
- // Some time later...
- $('#fun').tooltip('destroy');
在这个例子中, tooltip 在 init 方法中初始化, 它将 reposition 方法绑定到 Windows 对象的 resize 事件的 tooltip 名字空间下. 稍候, 如果开发者需要去掉这个 tooltip, 我们可以解绑这个绑定. 这样就不会影响到其他绑定到 Windows 对象的 resize 事件的方法了.
c, 数据
在开发插件的时候, 你通常会有保持状态或者检查你的插件是否已经初始化的需要. 使用 jQuery 的 data 方法是保持变量的很好的方法. 但是, 我们不把变量单独保存, 而是放在一个对象中, 这样就可以在一个名字空间下统一访问了.
- (function( $ ){
- var methods = {
- init : function( options ) {
- return this.each(function(){
- var $this = $(this),
- data = $this.data('tooltip'),
- tooltip = $('<div />', {
- text : $this.attr('title')
- });
- // If the plugin hasn't been initialized yet
- if ( ! data ) {
- /*
- Do more setup stuff here
- */
- $(this).data('tooltip', {
- target : $this,
- tooltip : tooltip
- });
- }
- });
- },
- destroy : function( ) {
- return this.each(function(){
- var $this = $(this),
- data = $this.data('tooltip');
- // Namespacing FTW
- $(Windows).unbind('.tooltip');
- data.tooltip.remove();
- $this.removeData('tooltip');
- })
- },
- reposition : function( ) { // ... },
- show : function( ) { // ... },
- hide : function( ) { // ... },
- update : function( content ) { // ...}
- };
- $.fn.tooltip = function( method ) {
- if ( methods[method] ) {
- return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
- } else if ( typeof method === 'object' || ! method ) {
- return methods.init.apply( this, arguments );
- } else {
- $.error( 'Method' + method + 'does not exist on jQuery.tooltip' );
- }
- };
- })( jQuery );
使用 data 方法可以帮助你在插件的各个方法间保持变量和状态. 将各种变量放在一个对象中, 可以方便访问, 也可以方便移除.
7, 总结与最佳实践
编写 jQuery 插件可以充分利用库, 将公用的函数抽象出来,"循环利用". 以下是简短的总结:
● 使用 (function($){//plugin})(jQuery); 来包装你的插件
● 不要在插件的初始范围中重复包裹
● 除非你返回原始值, 否则返回 this 指针来保证可链式
● 不要用一串参数, 而是使用一个对象, 并且设置默认值
● 一个插件, 不要为 jQuery.fn 附上多个函数
● 为你的函数, 事件, 数据附着到某个命名空间
来源: http://www.bubuko.com/infodetail-2879677.html