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

Javascript 如何使用方法创建jQuery插件?,javascript,jquery,jquery-plugins,javascript-framework,Javascript,Jquery,Jquery Plugins,Javascript Framework,我正在尝试编写一个jQuery插件,它将为调用它的对象提供额外的函数/方法。我在网上阅读的所有教程(过去两个小时一直在浏览)最多包括如何添加选项,但不包括附加功能 以下是我希望做的事情: //通过调用div的插件将div格式化为消息容器 $("#mydiv").messagePlugin(); $("#mydiv").messagePlugin().saySomething("hello"); 或者类似的东西。 这里是它归结为:我调用插件,然后调用与该插件关联的函数。我似乎找不到一种方法来做这

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

以下是我希望做的事情:

//通过调用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的以下评论和投票。

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

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

这种方法怎么样:

jQuery.fn.messagePlugin = function(){
    var selectedObjects = this;
    return {
             saySomething : function(message){
                              $(selectedObjects).each(function(){
                                $(this).html(message);
                              });
                              return selectedObjects; // Preserve the jQuery chainability 
                            },
             anotherAction : function(){
                               //...
                               return selectedObjects;
                             }
           };
}
// Usage:
$('p').messagePlugin().saySomething('I am a Paragraph').css('color', 'red');
选定对象存储在messagePlugin闭包中,该函数返回一个对象,该对象包含与插件关联的函数,在每个函数中,您可以对当前选定的对象执行所需的操作

您可以测试和使用代码


编辑:更新了代码以保留jQuery可链接性的功能。

一种更简单的方法是使用嵌套函数。然后您可以以面向对象的方式链接它们。例如:

jQuery.fn.MyPlugin = function()
{
  var _this = this;
  var a = 1;

  jQuery.fn.MyPlugin.DoSomething = function()
  {
    var b = a;
    var c = 2;

    jQuery.fn.MyPlugin.DoSomething.DoEvenMore = function()
    {
      var d = a;
      var e = c;
      var f = 3;
      return _this;
    };

    return _this;
  };

  return this;
};
以下是如何称呼它:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();
不过要小心。在创建嵌套函数之前,不能调用该函数。所以你不能这样做:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();
pluginContainer.MyPlugin.DoSomething();
DoEvenMore函数甚至不存在,因为DoSomething函数尚未运行,这是创建DoEvenMore函数所必需的。对于大多数jQuery插件,您实际上只需要一个级别的嵌套函数,而不是我在这里介绍的两个级别。
只要确保在创建嵌套函数时,在执行父函数中的任何其他代码之前,在父函数的开头定义这些函数


最后,请注意,“this”成员存储在一个名为“_this”的变量中。对于嵌套函数,如果需要调用客户端中实例的引用,则应返回“\u this”。不能只在嵌套函数中返回“this”,因为这将返回对函数的引用,而不是对jQuery实例的引用。返回jQuery引用允许您在返回时链接内部jQuery方法。

根据jQuery插件编写页面(),最好不要弄乱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“arguments”变量是传递的所有参数的数组,因此它可以处理任意长度的函数参数。

您所做的基本上是通过新方法扩展jQuery.fn.messagePlugin对象。这是有用的,但对你来说不是

你要做的就是使用这种技术

function methodA(args){ this // refers to object... }
function saySomething(message){ this.html(message);  to first function }

jQuery.fn.messagePlugin = function(opts) {
  if(opts=='methodA') methodA.call(this);
  if(opts=='saySomething') saySomething.call(this, arguments[0]); // arguments is an array of passed parameters
  return this.each(function(){
    alert(this);
  });

};

但是你可以实现你想要的我的意思是有一种方法可以做到$(“#mydiv”).messagePlugin().saySomething(“你好”);我的朋友,他开始写关于lugins的文章,以及如何用你的功能链来扩展它们这里是到

jQuery的链接,通过引入

示例:

$.widget( "myNamespace.myPlugin", {

    options: {
        // Default options
    },

    _create: function() {
        // Initialization logic here
    },

    // Create a public method.
    myPublicMethod: function( argument ) {
        // ...
    },

    // Create a private method.
    _myPrivateMethod: function( argument ) {
        // ...
    }

});
$('#my-element').myPlugin();
$('#my-element').myPlugin( {defaultValue:10} );
$('#my-element').myPlugin('myPublicMethod', 20);
初始化:

$.widget( "myNamespace.myPlugin", {

    options: {
        // Default options
    },

    _create: function() {
        // Initialization logic here
    },

    // Create a public method.
    myPublicMethod: function( argument ) {
        // ...
    },

    // Create a private method.
    _myPrivateMethod: function( argument ) {
        // ...
    }

});
$('#my-element').myPlugin();
$('#my-element').myPlugin( {defaultValue:10} );
$('#my-element').myPlugin('myPublicMethod', 20);
方法调用:

$.widget( "myNamespace.myPlugin", {

    options: {
        // Default options
    },

    _create: function() {
        // Initialization logic here
    },

    // Create a public method.
    myPublicMethod: function( argument ) {
        // ...
    },

    // Create a private method.
    _myPrivateMethod: function( argument ) {
        // ...
    }

});
$('#my-element').myPlugin();
$('#my-element').myPlugin( {defaultValue:10} );
$('#my-element').myPlugin('myPublicMethod', 20);

(这就是库的构建方式。)

使用触发器怎么样?有人知道使用它们有什么缺点吗? 好处是所有内部变量都可以通过触发器访问,代码非常简单

再见

示例用法
这是消息容器。。。
var mp=$(“#mydiv”).messagePlugin();
//插件返回调用它的元素
触发器(“messagePlugin.saySomething”,“hello”);
//所以不需要定义mp变量。。。
$(“#mydiv”).trigger(“messagePlugin.repeatLastMessage”);
插件
jQuery.fn.messagePlugin=function(){
返回此值。每个(函数(){
最后一条消息,
$this=$(this);
$this.on('messagePlugin.saySomething',函数(e,message){
lastmessage=消息;
说点什么(信息);
});
$this.on('messagePlugin.repeatLastMessage',函数(e){
repeatLastMessage();
});
函数saySomething(消息){
$this.html(“”+消息+“

”); } 函数repeatLastMessage(){ $this.append(“最后一条消息是:“+lastmessage+”

”); } }); }
当前所选答案的问题在于,您实际上并没有像您认为的那样为选择器中的每个元素创建自定义插件的新实例。。。实际上,您只创建了一个实例,并将选择器本身作为作用域传入

查看以获得更深入的解释

相反,您需要使用循环遍历选择器,并为选择器中的每个元素实例化自定义插件的新实例

以下是方法:

(function($) {

    var CustomPlugin = function($el, options) {

        this._defaults = {
            randomizer: Math.random()
        };

        this._options = $.extend(true, {}, this._defaults, options);

        this.options = function(options) {
            return (options) ?
                $.extend(true, this._options, options) :
                this._options;
        };

        this.move = function() {
            $el.css('margin-left', this._options.randomizer * 100);
        };

    };

    $.fn.customPlugin = function(methodOrOptions) {

        var method = (typeof methodOrOptions === 'string') ? methodOrOptions : undefined;

        if (method) {
            var customPlugins = [];

            function getCustomPlugin() {
                var $el          = $(this);
                var customPlugin = $el.data('customPlugin');

                customPlugins.push(customPlugin);
            }

            this.each(getCustomPlugin);

            var args    = (arguments.length > 1) ? Array.prototype.slice.call(arguments, 1) : undefined;
            var results = [];

            function applyMethod(index) {
                var customPlugin = customPlugins[index];

                if (!customPlugin) {
                    console.warn('$.customPlugin not instantiated yet');
                    console.info(this);
                    results.push(undefined);
                    return;
                }

                if (typeof customPlugin[method] === 'function') {
                    var result = customPlugin[method].apply(customPlugin, args);
                    results.push(result);
                } else {
                    console.warn('Method \'' + method + '\' not defined in $.customPlugin');
                }
            }

            this.each(applyMethod);

            return (results.length > 1) ? results : results[0];
        } else {
            var options = (typeof methodOrOptions === 'object') ? methodOrOptions : undefined;

            function init() {
                var $el          = $(this);
                var customPlugin = new CustomPlugin($el, options);

                $el.data('customPlugin', customPlugin);
            }

            return this.each(init);
        }

    };

})(jQuery);
还有一个

您会注意到,在第一小提琴中,所有div始终向右移动,像素数完全相同。这是因为选择器中的所有元素只存在一个选项对象

使用上面写的技术,您会注意到在第二个提琴中,每个div都没有对齐,而是随机移动的(不包括第一个div,因为它的随机化器在第89行总是设置为1)。这是因为我们现在正确地实例化了一个新的自定义插件i
$('#myDiv').MessagePlugin({ yourSettings: 'here' })
           .MessagePlugin('saySomething','Hello World!');
$elem = $('#myDiv').MessagePlugin();
var instance = $elem.data('plugin_MessagePlugin');
instance.saySomething('Hello World!');
;(function($){

    function MessagePlugin(element,settings){ // The Plugin
        this.$elem = element;
        this._settings = settings;
        this.settings = $.extend(this._default,settings);
    }

    MessagePlugin.prototype = { // The Plugin prototype
        _default: {
            message: 'Generic message'
        },
        initialize: function(){},
        saySomething: function(message){
            message = message || this._default.message;
            return this.$elem.html(message);
        }
    };

    $.fn.MessagePlugin = function(settings){ // The Plugin call

        var instance = this.data('plugin_MessagePlugin'); // Get instance

        if(instance===undefined){ // Do instantiate if undefined
            settings = settings || {};
            this.data('plugin_MessagePlugin',new MessagePlugin(this,settings));
            return this;
        }

        if($.isFunction(MessagePlugin.prototype[settings])){ // Call method if argument is name of method
            var args = Array.prototype.slice.call(arguments); // Get the arguments as Array
            args.shift(); // Remove first argument (name of method)
            return MessagePlugin.prototype[settings].apply(instance, args); // Call the method
        }

        // Do error handling

        return this;
    }

})(jQuery);
function $_color(color)
{
    return this.css('color', color);
}

function $_color_blue()
{
    return this.css('color', 'blue');
}

Object.defineProperty($.fn, 'color',
{
    enumerable: true,
    get: function()
    {
        var self = this;

        var ret = function() { return $_color.apply(self, arguments); }
        ret.blue = function() { return $_color_blue.apply(self, arguments); }

        return ret;
    }
});

$('#foo').color('#f00');
$('#bar').color.blue();
(function($) {

    //methods starts here....
    var methods = {
        init : function(method,options) {
             this.loadKeywords.settings = $.extend({}, this.loadKeywords.defaults, options);
             methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
             $loadkeywordbase=$(this);
        },
        show : function() {
            //your code here.................
        },
        getData : function() {
           //your code here.................
        }

    } // do not put semi colon here otherwise it will not work in ie7
    //end of methods

    //main plugin function starts here...
    $.fn.loadKeywords = function(options,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 ecw-Keywords');
        }
    };
    $.fn.loadKeywords.defaults = {
            keyName:     'Messages',
            Options:     '1',
            callback: '',
    };
    $.fn.loadKeywords.settings = {};
    //end of plugin keyword function.

})(jQuery);
1.$('your element').loadKeywords('show',{'callback':callbackdata,'keyName':'myKey'}); // show() will be called
jQuery.fn.warning = function() {
   return this.each(function() {
      alert('Tag Name:"' + $(this).prop("tagName") + '".');
   });
};
<html>
   <head>
      <title>The jQuery Example</title>

      <script type = "text/javascript" 
         src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

      <script src = "jquery.debug.js" type = "text/javascript"></script>

      <script type = "text/javascript" language = "javascript">
         $(document).ready(function() {
            $("div").warning();
            $("p").warning();
         });
      </script> 
   </head>

   <body>
      <p>This is paragraph</p>
      <div>This is division</div>
   </body>

</html>
(function ( $ ) {

$.fn.gridview = function( options ) {

    ..........
    ..........


    var factory = new htmlFactory();
    factory.header(...);

    ........

};

}( jQuery ));


var htmlFactory = function(){

    //header
     this.header = function(object){
       console.log(object);
  }
 }
(function($, window, undefined) { 
  const defaults = {
    elementId   : null,
    shape       : "square",
    color       : "aqua",
    borderWidth : "10px",
    borderColor : "DarkGray"
  };

  $.fn.myPlugin = function(options) {
    // settings, e.g.:  
    var settings = $.extend({}, defaults, options);

    // private methods, e.g.:
    var setBorder = function(color, width) {        
      settings.borderColor = color;
      settings.borderWidth = width;          
      drawShape();
    };

    var drawShape = function() {         
      $('#' + settings.elementId).attr('class', settings.shape + " " + "center"); 
      $('#' + settings.elementId).css({
        'background-color': settings.color,
        'border': settings.borderWidth + ' solid ' + settings.borderColor      
      });
      $('#' + settings.elementId).html(settings.color + " " + settings.shape);            
    };

    return this.each(function() { // jQuery chainability     
      // set stuff on ini, e.g.:
      settings.elementId = $(this).attr('id'); 
      drawShape();

      // PUBLIC INTERFACE 
      // gives us stuff like: 
      //
      //    $("#...").data('myPlugin').myPublicPluginMethod();
      //
      var myPlugin = {
        element: $(this),
        // access private plugin methods, e.g.: 
        setBorder: function(color, width) {        
          setBorder(color, width);
          return this.element; // To ensure jQuery chainability 
        },
        // access plugin settings, e.g.: 
        color: function() {
          return settings.color;
        },        
        // access setting "shape" 
        shape: function() {
          return settings.shape;
        },     
        // inspect settings 
        inspectSettings: function() {
          msg = "inspecting settings for element '" + settings.elementId + "':";   
          msg += "\n--- shape: '" + settings.shape + "'";
          msg += "\n--- color: '" + settings.color + "'";
          msg += "\n--- border: '" + settings.borderWidth + ' solid ' + settings.borderColor + "'";
          return msg;
        },               
        // do stuff on element, e.g.:  
        change: function(shape, color) {        
          settings.shape = shape;
          settings.color = color;
          drawShape();   
          return this.element; // To ensure jQuery chainability 
        }
      };
      $(this).data("myPlugin", myPlugin);
    }); // return this.each 
  }; // myPlugin
}(jQuery));
$("#...").data('myPlugin').myPublicPluginMethod(); 
$("#...").data('myPlugin').myPublicPluginMethod().css("color", "red").html("...."); 
// initialize plugin on elements, e.g.:
$("#shape1").myPlugin({shape: 'square', color: 'blue', borderColor: 'SteelBlue'});
$("#shape2").myPlugin({shape: 'rectangle', color: 'red', borderColor: '#ff4d4d'});
$("#shape3").myPlugin({shape: 'circle', color: 'green', borderColor: 'LimeGreen'});

// calling plugin methods to read element specific plugin settings:
console.log($("#shape1").data('myPlugin').inspectSettings());    
console.log($("#shape2").data('myPlugin').inspectSettings());    
console.log($("#shape3").data('myPlugin').inspectSettings());      

// calling plugin methods to modify elements, e.g.:
// (OMG! And they are chainable too!) 
$("#shape1").data('myPlugin').change("circle", "green").fadeOut(2000).fadeIn(2000);      
$("#shape1").data('myPlugin').setBorder('LimeGreen', '30px');

$("#shape2").data('myPlugin').change("rectangle", "red"); 
$("#shape2").data('myPlugin').setBorder('#ff4d4d', '40px').css({
  'width': '350px',
  'font-size': '2em' 
}).slideUp(2000).slideDown(2000);              

$("#shape3").data('myPlugin').change("square", "blue").fadeOut(2000).fadeIn(2000);   
$("#shape3").data('myPlugin').setBorder('SteelBlue', '30px');

// etc. ...