【问题标题】:How to create a jQuery plugin with methods?如何使用方法创建 jQuery 插件?
【发布时间】:2024-04-29 04:45:02
【问题描述】:

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

这是我想做的事情:

//通过调用该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 的以下 cmets 和 upvotes。

【问题讨论】:

    标签: javascript jquery jquery-plugins javascript-framework


    【解决方案1】:

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

    $('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-ui 相同的模式,我不喜欢所有的魔术字符串,但有没有其他方法!
    • 这似乎是一种非标准的做事方式——还有什么比这更简单的吗,比如链接函数?谢谢!
    • @yuval -- 通常 jQuery 插件返回 jQuery 或一个值,而不是插件本身。这就是为什么当您想要调用插件时方法的名称作为参数传递给插件的原因。您可以传递任意数量的参数,但您必须调整函数和参数解析。可能最好将它们设置在您展示的匿名对象中。
    • 你第一行的;是什么意思?请给我解释一下:)
    • @GusDeCooL 它只是确保我们正在开始一个新语句,以便我们的函数定义不会被解释为其他人格式错误的 Javascript 的参数(即,不采用初始括号作为函数调用运算符)。见*.com/questions/7365172/…
    【解决方案2】:

    这种方法怎么样:

    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 闭包中,该函数返回一个包含与插件关联的函数的对象,在每个函数中,您可以对当前选定的对象执行所需的操作。

    您可以测试和使用代码here

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

    【讨论】:

    • 我有点难以理解这会是什么样子。假设我有需要在第一次运行时执行的代码,我必须首先在我的代码中初始化它 - 像这样: $('p').messagePlugin();然后稍后在代码中我想调用这样的函数 saySomething $('p').messagePlugin().saySomething('something');这不会重新初始化插件然后调用函数吗?外壳和选项会是什么样子?非常感谢您。 -yuval
    • 不过,在某种程度上打破了 jQuery 的可链接性范式。
    • 也许这应该是最好的答案
    • 每次调用 messagePlugin() 都会用这两个函数创建一个新对象,不是吗?
    • 这种方法的主要问题是它无法在$('p').messagePlugin() 之后保持可链接性,除非您调用它返回的两个函数之一。
    【解决方案3】:

    更简单的方法是使用嵌套函数。然后,您可以以面向对象的方式将它们链接起来。示例:

    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 函数甚至不存在,因为尚未运行创建 DoEvenMore 函数所需的 DoSomething 函数。对于大多数 jQuery 插件,您实际上只会拥有一层嵌套函数,而不是我在这里展示的两层。
    只需确保在创建嵌套函数时,在父函数中的任何其他代码执行之前,在其父函数的开头定义这些函数。

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

    【讨论】:

    • 这太棒了——我只是想知道为什么 jQuery 似乎更喜欢在 .plugin('method') 模式中按名称调用方法?
    • 这不起作用。如果您在两个不同的容器上调用插件,内部变量将被覆盖(即 _this)
    • 失败:不允许 pluginContainer.MyPlugin.DoEvenMore().DoSomething();
    【解决方案4】:

    根据 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 );
    

    基本上,您将函数存储在数组中(范围为包装函数),如果传递的参数是字符串,则检查条目,如果参数是对象(或空)。

    然后你可以像这样调用方法......

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

    Javascript 的“arguments”变量是一个包含所有传递参数的数组,因此它适用于任意长度的函数参数。

    【讨论】:

    • 这是我使用的方法。您也可以通过 $.fn.tooltip('methodname', params); 静态调用方法;​​
    • 非常方便的架构。我还在调用 init 方法之前添加了这一行:this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));,所以现在我可以在初始化后随时访问选项。
    • 对于像我这样第一次说“参数变量从何而来”的人-developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…-我一直在使用 JS,但从来不知道。你每天都能学到新东西!
    • @DiH,我支持你。这种方法看起来很棒,但它不能让您从init 以外的任何地方访问您的全局设置。
    • 这种技术有一个大问题!它不会像您认为的那样为选择器中的每个元素创建一个新实例,而是只创建一个附加到选择器本身的实例。查看my answer 以获得解决方案。
    【解决方案5】:

    您所做的基本上是通过新方法扩展 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("hello");我的朋友他开始写关于 lugins 以及如何使用你的 chainf 功能扩展它们的链接是his blog

    【讨论】:

      【解决方案6】:

      jQuery 通过引入Widget Factory 让这一切变得更加容易。

      示例:

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

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

      【讨论】:

      • @daniel.sedlacek a) “非常糟糕的架构” - 它是 jQuery 的标准小部件架构 b) “在编译时检查完整性” - JavaScript 是一种动态语言 c) “TypeScript” - 什么?
      • a) 那是争论的焦点,b) 每个更好的 JS IDE 都有代码完成或 linting,c) 谷歌它
      • 这纯粹是错觉,Sedlacek 先生。
      • Per docs: 这个系统被称为 Widget Factory,作为 jQuery UI 1.8 的一部分公开为 jQuery.widget;但是,它可以独立于 jQuery UI 使用。 $.widget 如何在没有 jQuery UI 的情况下使用?
      【解决方案7】:

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

      参见jsfiddle

      示例用法

      <div id="mydiv">This is the message container...</div>
      
      <script>
          var mp = $("#mydiv").messagePlugin();
      
          // the plugin returns the element it is called on
          mp.trigger("messagePlugin.saySomething", "hello");
      
          // so defining the mp variable is not needed...
          $("#mydiv").trigger("messagePlugin.repeatLastMessage");
      </script>
      

      插件

      jQuery.fn.messagePlugin = function() {
      
          return this.each(function() {
      
              var lastmessage,
                  $this = $(this);
      
              $this.on('messagePlugin.saySomething', function(e, message) {
                  lastmessage = message;
                  saySomething(message);
              });
      
              $this.on('messagePlugin.repeatLastMessage', function(e) {
                  repeatLastMessage();
              });
      
              function saySomething(message) {
                  $this.html("<p>" + message + "</p>");
              }
      
              function repeatLastMessage() {
                  $this.append('<p>Last message was: ' + lastmessage + '</p>');
              }
      
          });
      
      }
      

      【讨论】:

      • 参见。你的评论。我在这里看到的唯一问题可以说是对事件系统的滥用。纯粹使用事件来调用函数是不典型的;这似乎是矫枉过正,可能很容易被打破。通常,您会以发布-订阅方式使用事件,例如,一个函数发布某个条件“A”已发生。其他对“A”感兴趣的实体会监听“A”已经发生的消息,然后做一些事情。您似乎将其用作推送“命令”,但假设只有一个侦听器。您需要小心,不要因(其他人)添加侦听器而破坏您的语义。
      • @tvanfosson 感谢您的评论。我知道这不是常见的技术,如果有人不小心添加了一个事件侦听器,它可能会导致问题,但如果它以插件命名,则不太可能。我不知道任何与性能相关的问题,但代码本身对我来说似乎比其他解决方案要简单得多,但我可能会遗漏一些东西。
      【解决方案8】:

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

      查看this fiddle以获得更深入的解释。

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

      方法如下:

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

      还有一个working fiddle

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

      使用上面编写的技术,您会注意到在第二个小提琴中,每个 div 都没有对齐并且是随机移动的(不包括第一个 div,因为它的随机化器在第 89 行始终设置为 1)。那是因为我们现在正在为选择器中的每个元素正确地实例化一个新的自定义插件实例。每个元素都有自己的选项对象,并且不保存在选择器中,而是保存在自定义插件本身的实例中。

      这意味着您将能够从新的 jQuery 选择器访问在 DOM 中特定元素上实例化的自定义插件的方法,而不必像在第一个小提琴中那样强制缓存它们。

      例如,这将使用第二把小提琴中的技术返回一个包含所有选项对象的数组。它会在第一个返回 undefined。

      $('div').customPlugin();
      $('div').customPlugin('options'); // would return an array of all options objects
      

      这就是您必须在第一个小提琴中访问选项对象的方式,并且只会返回一个对象,而不是它们的数组:

      var divs = $('div').customPlugin();
      divs.customPlugin('options'); // would return a single options object
      
      $('div').customPlugin('options');
      // would return undefined, since it's not a cached selector
      

      我建议使用上述技术,而不是当前选择的答案。

      【讨论】:

      • 谢谢,这对我帮助很大,特别是向我介绍了 .data() 方法。非常便利。 FWIW,您还可以使用匿名方法简化一些代码。
      • 使用此方法无法使用 jQuery 链接性...$('.my-elements').find('.first-input').customPlugin('update'‌​, 'first value').end().find('.second-input').customPlugin('update', 'second value'); returns Cannot read property 'end' of undefinedjsfiddle.net/h8v1k2pL
      【解决方案9】:

      为时已晚,但也许有一天它可以帮助某人。

      我遇到了同样的情况,使用一些方法创建了一个 jQuery 插件,在阅读了一些文章和一些轮胎之后,我创建了一个 jQuery 插件样板 (https://github.com/acanimal/jQuery-Plugin-Boilerplate)。

      此外,我用它开发了一个插件来管理标签(https://github.com/acanimal/tagger.js),并写了两篇博文,逐步解释了 jQuery 插件的创建(http://acuriousanimal.com/blog/2013/01/15/things-i-learned-creating-a-jquery-plugin-part-i/)。

      【讨论】:

      • 可能是我遇到的关于作为初学者创建 jQuery 插件的最佳帖子 - 谢谢 ;)
      • 感谢您采用这种理智的方法。正确地创建 jQuery 插件实在是太复杂了。这确实是 jQuery 和整个 Javascript 的一个主要弱点,因为它的原型很奇怪。
      【解决方案10】:

      我从jQuery Plugin Boilerplate得到它

      jQuery Plugin Boilerplate, reprise中也有描述

      // jQuery Plugin Boilerplate
      // A boilerplate for jumpstarting jQuery plugins development
      // version 1.1, May 14th, 2011
      // by Stefan Gabos
      
      // remember to change every instance of "pluginName" to the name of your plugin!
      (function($) {
      
          // here we go!
          $.pluginName = function(element, options) {
      
          // plugin's default options
          // this is private property and is accessible only from inside the plugin
          var defaults = {
      
              foo: 'bar',
      
              // if your plugin is event-driven, you may provide callback capabilities
              // for its events. execute these functions before or after events of your
              // plugin, so that users may customize those particular events without
              // changing the plugin's code
              onFoo: function() {}
      
          }
      
          // to avoid confusions, use "plugin" to reference the
          // current instance of the object
          var plugin = this;
      
          // this will hold the merged default, and user-provided options
          // plugin's properties will be available through this object like:
          // plugin.settings.propertyName from inside the plugin or
          // element.data('pluginName').settings.propertyName from outside the plugin,
          // where "element" is the element the plugin is attached to;
          plugin.settings = {}
      
          var $element = $(element), // reference to the jQuery version of DOM element
          element = element; // reference to the actual DOM element
      
          // the "constructor" method that gets called when the object is created
          plugin.init = function() {
      
          // the plugin's final properties are the merged default and
          // user-provided options (if any)
          plugin.settings = $.extend({}, defaults, options);
      
          // code goes here
      
         }
      
         // public methods
         // these methods can be called like:
         // plugin.methodName(arg1, arg2, ... argn) from inside the plugin or
         // element.data('pluginName').publicMethod(arg1, arg2, ... argn) from outside
         // the plugin, where "element" is the element the plugin is attached to;
      
         // a public method. for demonstration purposes only - remove it!
         plugin.foo_public_method = function() {
      
         // code goes here
      
          }
      
           // private methods
           // these methods can be called only from inside the plugin like:
           // methodName(arg1, arg2, ... argn)
      
           // a private method. for demonstration purposes only - remove it!
           var foo_private_method = function() {
      
              // code goes here
      
           }
      
           // fire up the plugin!
           // call the "constructor" method
           plugin.init();
      
           }
      
           // add the plugin to the jQuery.fn object
           $.fn.pluginName = function(options) {
      
              // iterate through the DOM elements we are attaching the plugin to
              return this.each(function() {
      
                // if plugin has not already been attached to the element
                if (undefined == $(this).data('pluginName')) {
      
                    // create a new instance of the plugin
                    // pass the DOM element and the user-provided options as arguments
                    var plugin = new $.pluginName(this, options);
      
                    // in the jQuery version of the element
                    // store a reference to the plugin object
                    // you can later access the plugin and its methods and properties like
                    // element.data('pluginName').publicMethod(arg1, arg2, ... argn) or
                    // element.data('pluginName').settings.propertyName
                    $(this).data('pluginName', plugin);
      
                 }
      
              });
      
          }
      
      })(jQuery);
      

      【讨论】:

      • 你的方法破坏了 jQuery 链接:$('.first-input').data('pluginName').publicMethod('new value').css('color', red); 返回 Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
      • @AlexG 在此示例中,您将添加 return $element,因此在此示例中,您将其更改为 plugin.foo_public_method = function() {/* Your Code */ return $element;} @Salim 感谢您的帮助... github.com/AndreaLombardo/BootSideMenu/pull/34
      【解决方案11】:

      试试这个:

      $.fn.extend({
      "calendar":function(){
          console.log(this);
          var methods = {
                  "add":function(){console.log("add"); return this;},
                  "init":function(){console.log("init"); return this;},
                  "sample":function(){console.log("sample"); return this;}
          };
      
          methods.init(); // you can call any method inside
          return methods;
      }}); 
      $.fn.calendar() // caller or 
      $.fn.calendar().sample().add().sample() ......; // call methods
      

      【讨论】:

        【解决方案12】:

        这是我的基本版本。与之前发布的类似,您可以这样称呼:

        $('#myDiv').MessagePlugin({ yourSettings: 'here' })
                   .MessagePlugin('saySomething','Hello World!');
        

        -或者直接访问实例@plugin_MessagePlugin

        $elem = $('#myDiv').MessagePlugin();
        var instance = $elem.data('plugin_MessagePlugin');
        instance.saySomething('Hello World!');
        

        MessagePlugin.js

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

        【讨论】:

          【解决方案13】:

          这实际上可以使用defineProperty 以“很好”的方式工作。其中“nice”意味着不必使用() 来获取插件命名空间,也不必通过字符串传递函数名。

          兼容性问题: defineProperty 不适用于 IE8 及以下旧版浏览器。 警告: $.fn.color.blue.apply(foo, args) 不起作用,您需要使用 foo.color.blue.apply(foo, args)

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

          JSFiddle link

          【讨论】:

            【解决方案14】:

            根据 jquery 标准,您可以按如下方式创建插件:

            (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
            

            参考:link

            【讨论】:

              【解决方案15】:

              我想这可能会对你有所帮助...

              (function ( $ ) {
                
                  $.fn.highlight = function( options ) {
                
                      // This is the easiest way to have default options.
                      var settings = $.extend({
                          // These are the defaults.
                          color: "#000",
                          backgroundColor: "yellow"
                      }, options );
                
                      // Highlight the collection based on the settings variable.
                      return this.css({
                          color: settings.color,
                          backgroundColor: settings.backgroundColor
                      });
                
                  };
                
              }( jQuery ));

              在上面的示例中,我创建了一个简单的 jquery highlight 插件。我分享了一篇文章,其中讨论了关于 如何从 Basic 中创建自己的 jQuery 插件推进。 我认为您应该检查一下...http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/

              【讨论】:

                【解决方案16】:

                以下是一个小插件,具有用于调试目的的警告方法。将此代码保存在 jquery.debug.js 文件中: JS:

                jQuery.fn.warning = function() {
                   return this.each(function() {
                      alert('Tag Name:"' + $(this).prop("tagName") + '".');
                   });
                };
                

                HTML:

                <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>
                

                【讨论】:

                  【解决方案17】:

                  这是我的做法:

                  (function ( $ ) {
                  
                  $.fn.gridview = function( options ) {
                  
                      ..........
                      ..........
                  
                  
                      var factory = new htmlFactory();
                      factory.header(...);
                  
                      ........
                  
                  };
                  
                  }( jQuery ));
                  
                  
                  var htmlFactory = function(){
                  
                      //header
                       this.header = function(object){
                         console.log(object);
                    }
                   }
                  

                  【讨论】:

                    【解决方案18】:

                    你可以这样做:

                    (function($) {
                      var YourPlugin = function(element, option) {
                        var defaults = {
                          //default value
                        }
                    
                        this.option = $.extend({}, defaults, option);
                        this.$element = $(element);
                        this.init();
                      }
                    
                      YourPlugin.prototype = {
                        init: function() { },
                        show: function() { },
                        //another functions
                      }
                    
                      $.fn.yourPlugin = function(option) {
                        var arg = arguments,
                            options = typeof option == 'object' && option;;
                        return this.each(function() {
                          var $this = $(this),
                              data = $this.data('yourPlugin');
                    
                          if (!data) $this.data('yourPlugin', (data = new YourPlugin(this, options)));
                          if (typeof option === 'string') {
                            if (arg.length > 1) {
                              data[option].apply(data, Array.prototype.slice.call(arg, 1));
                            } else {
                              data[option]();
                            }
                          }
                        });
                      };
                    });
                    

                    通过这种方式,您的插件对象将作为数据值存储在您的元素中。

                    //Initialization without option
                    $('#myId').yourPlugin();
                    
                    //Initialization with option
                    $('#myId').yourPlugin({
                      // your option
                    });
                    
                    // call show method
                    $('#myId').yourPlugin('show');
                    

                    【讨论】:

                      【解决方案19】:

                      在这里,我想建议一些步骤来创建带有参数的简单插件。

                      (function($) {
                        $.fn.myFirstPlugin = function(options) {
                          // Default params
                          var params = $.extend({
                            text     : 'Default Title',
                            fontsize : 10,
                          }, options);
                          return $(this).text(params.text);
                        }
                      }(jQuery));
                      
                      $('.cls-title').myFirstPlugin({ text : 'Argument Title' });
                      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                      <h1 class="cls-title"></h1>

                      在这里,我们添加了名为params 的默认对象,并使用extend 函数设置选项的默认值。因此,如果我们传递空白参数,那么它将设置默认值,否则它将设置。

                      阅读全文: How to Create JQuery plugin

                      【讨论】:

                      • 嗨 Gopal Joshi ,请创建下一级 jquery 插件。我们期待您的必要回答。
                      • 你好@SakthiKarthik,我很快就会在我的博客中发布新教程
                      • 嗨@SakthiKarthik,你可以在这里参考关于下一级jquery插件的新文章sgeek.org/…
                      【解决方案20】:

                      以下插件结构利用 jQuery-data()-method 为内部插件方法/设置提供公共接口(同时保留 jQuery-chainability):

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

                      只要你从myPublicPluginMethod()jQuery-chainability 的实现中返回当前元素(this) 将被保留 - 所以以下工作:

                      $("#...").data('myPlugin').myPublicPluginMethod().css("color", "red").html("...."); 
                      

                      以下是一些示例(详情请查看此fiddle):

                      // 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. ...     
                      

                      【讨论】: