jQuery 插件创作和命名空间

Posted

技术标签:

【中文标题】jQuery 插件创作和命名空间【英文标题】:jQuery Plugin Authoring and Namespacing 【发布时间】:2012-09-19 21:19:16 【问题描述】:

我习惯这样写插件:

;(function($)jQuery.fn.myPlugin=function(options)
    var defaults=
        'property':value
    ,
    o=$.extend(,defaults,options||);

   // INSERT AND CACHE ELEMENTS
   var $Element=$('<div></div>');
   $Element.appendTo($('body'));

function funFunction()
  // I have access to $Element!
 $Element.hide(500);
;

this.each(function(i)
     var $this=$(this);
);
return this;
);;)(jQuery);

我知道它并不完美,这就是我现在尝试正确学习命名空间、更好的插件结构/模式的原因。不幸的是,我读过的前几本书逐字引用了 jQuery 插件创作教程,因此并没有太大帮助。该教程似乎将所有内容分开,并没有展示一个很好的组合示例,这就是我感到困惑的原因。在本教程中,它显示了命名空间示例。

jQuery 插件命名空间教程

(function( $ )
  var methods = 
    init : function( options )  
    ,
    show : function( ) 
    ,
    hide : function( )  
    ,
    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 );
// calls the init method
$('div').tooltip(); 

我了解结构以及如何访问命名空间对象,但是它显示了不包括任何命名空间的默认值/选项的另一个示例......因此,为了编写正确命名空间的插件的开头,具有默认值/选项并缓存我插入的 html 元素以供整个插件使用,我想出了以下内容。

正确的组合?

;(function($,window,document,undefined)
var myPlugin=
    // METHODS
    init:function(options)

    ,
    buildElements:function() 
        var $Elements=$('<div id="myElem"></div>')
                    .appendTo($('body'));
       
;

$.fn.myPlugin=function(method,options)
    var defaults=

    ,
    options=$.extend(,defaults,options||);

    myPlugin.buildElements();

    return this.each(function()
        var $this=$(this);
        if(myPlugin[method])
          return myPlugin[method].apply(this,Array.prototype.slice.call(arguments,1));
        else if(typeof method==='object'||!method)
          return myPlugin.init.apply(this,arguments);
        else$.error('Method '+method+' does not exist on jQuery.myPlugin');;
    );
;)(jQuery);

    显然,当我构建/插入 myElem 时,它只能在该方法中使用,而不能在任何其他方法中使用......我是在错误的地方构建它吗?

    默认/扩展是否在正确的位置?

    如果我不想从插件外部访问方法,是否需要方法逻辑部分?

    使用 .prototype 与 .fn 相比有什么好处吗?

非常感谢所有人! :)

【问题讨论】:

向@FabrícioMatté 表达我见过的最好的 SO 评论 【参考方案1】:

更仔细地查看“工具提示”示例插件。这是一个真正伟大的模式。

它完成了您需要的所有命名空间,并且已经是您习惯的类型,至少底部的通用“主管”块是 - 即这部分:

$.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' );
        
;

methods 在简单的 javascript 术语中是一个私有变量,但它的属性被主管以一种非常聪明、非常规的方式公开为插件的方法。

请不要尝试将默认/选项代码移出 init 方法。这将把一切都搞砸了!遵循久经考验且值得信赖的模式,一切都会好起来的。

编辑:

一定要遵守模式的其他方面:

要保持 jQuery 对象可链接性,请在每个不返回特定结果的方法中使用 return this.each(function()...) 结构。 (通常),在 init 中,建立一个.data('pluninName', ...) 对象以容纳在初始化时建立的任何数据,并且稍后需要由其他插件方法访问/修改/增强。

该模式只为插件本身提供了一个闭包(包含methods 对象);闭包的命名空间不能用于元素特定的数据(包括初始化选项),因此需要使用.data('pluninName', ...)

这些不仅仅是约定——它们绝对是使模式按预期工作的关键。

【讨论】:

非常感谢您的回复!所以只是为了确保我理解:将选项/默认值保留在 init 方法中,然后在 fn.name 函数中调用它。我将在哪里构建和缓存插件元素,例如实际的工具提示 div?谢谢! :) 使用此模式,在执行插件代码后,jquery一个 新的自定义方法 - 示例中的“工具提示”。在使用中,插件的调用方式与其他方法相同,例如。 $(selector).tooltip(...); 但不同之处在于插件所需的“内部方法”被指定为第一个字符串参数$(selector).tooltip('methodName');(默认为“init”)。根据每个“内部方法”的要求,可以传递更多参数。此架构旨在帮助避免 $.fn 中的命名空间冲突,同时仍允许插件拥有丰富的方法集合。 再次感谢您的详细回答,我已投票并标记为答案 :) 一旦我解决了这个问题,我会发布完整的模板

以上是关于jQuery 插件创作和命名空间的主要内容,如果未能解决你的问题,请参考以下文章

我应该在 jquery 小部件上使用啥命名空间?

JQuery 命名空间是一个好习惯吗?

jQuery 命名空间的使用

浅谈jquery事件命名空间

JavaScript 命名空间和 jQuery 事件处理程序

使用命名空间调用 jquery