如何使用方法创建jQuery插件?

我正在尝试编写一个jQuery插件,该插件将为调用它的对象提供其他函数/方法。我在网上阅读的所有教程(在过去的2个小时里一直在浏览)最多包括如何添加选项,但没有其他功能。

以下是我想要做的:

format div 成为消息容器,方法是调用该 div 的插件

$("#mydiv").messagePlugin();
$("#mydiv").messagePlugin().saySomething("hello");

或类似的东西。它归结为:我调用插件,然后调用与该插件关联的函数。我似乎找不到做到这一点的方法,我以前见过很多插件这样做。

以下是我到目前为止对插件的内容:

jQuery.fn.messagePlugin = function() {
  return this.each(function(){
    alert(this);
  });

  //i tried to do this, but it does not seem to work
  jQuery.fn.messagePlugin.saySomething = function(message){
    $(this).html(message);
  }
};

我怎样才能实现这样的事情?

谢谢!


2013年11月18日更新:我已将正确答案更改为Hari的以下评论和赞成票。


答案 1

根据jQuery插件创作页面(http://docs.jquery.com/Plugins/Authoring),最好不要混淆jQuery和jQuery.fn命名空间。他们建议使用此方法:

(function( $ ){

    var methods = {
        init : function(options) {

        },
        show : function( ) {    },// IS
        hide : function( ) {  },// GOOD
        update : function( content ) {  }// !!!
    };

    $.fn.tooltip = function(methodOrOptions) {
        if ( methods[methodOrOptions] ) {
            return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
            // Default to "init"
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  methodOrOptions + ' does not exist on jQuery.tooltip' );
        }    
    };


})( jQuery );

基本上,您将函数存储在数组中(作用域为包装函数),并检查传递的参数是否是字符串的条目,如果参数是对象(或 null),则恢复为默认方法(此处为“init”)。

然后,您可以像这样调用这些方法...

$('div').tooltip(); // calls the init method
$('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

Javascripts“参数”变量是所有传递的参数的数组,因此它适用于任意长度的函数参数。


答案 2

这是我用于使用其他方法创建插件的模式。你可以像这样使用它:

$('selector').myplugin( { key: 'value' } );

或者,直接调用方法,

$('selector').myplugin( 'mymethod1', 'argument' );

例:

;(function($) {

    $.fn.extend({
        myplugin: function(options,arg) {
            if (options && typeof(options) == 'object') {
                options = $.extend( {}, $.myplugin.defaults, options );
            }

            // this creates a plugin for each element in
            // the selector or runs the function once per
            // selector.  To have it do so for just the
            // first element (once), return false after
            // creating the plugin to stop the each iteration 
            this.each(function() {
                new $.myplugin(this, options, arg );
            });
            return;
        }
    });

    $.myplugin = function( elem, options, arg ) {

        if (options && typeof(options) == 'string') {
           if (options == 'mymethod1') {
               myplugin_method1( arg );
           }
           else if (options == 'mymethod2') {
               myplugin_method2( arg );
           }
           return;
        }

        ...normal plugin actions...

        function myplugin_method1(arg)
        {
            ...do method1 with this and arg
        }

        function myplugin_method2(arg)
        {
            ...do method2 with this and arg
        }

    };

    $.myplugin.defaults = {
       ...
    };

})(jQuery);