如何创建一个带有方法的jQuery插件?

198
我正在尝试编写一个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的评论和赞数,我已将正确答案更改为他的回答。

20个回答

3

在这里,我想提供创建带有参数的简单插件的步骤。

(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函数设置选项的默认值。因此,如果我们传递空参数,则它将设置默认值,否则它将设置其他值。 阅读更多:如何创建jQuery插件

嗨,Gopal Joshi,能否请您提供下一级别的jQuery插件创建?我们期待着您的回答。 - Sakthi Karthik
你好@SakthiKarthik,当然我会很快在我的博客上发布新的教程。 - Gopal Joshi
1
嗨,@SakthiKarthik,你可以在这里参考下一级jQuery插件的新文章:http://sgeek.org/jquery-toggle-button-plugin-for-sliding-toggle-switches-sswitch/。 - Gopal Joshi

2

试试这个:

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

1
以下插件结构利用 jQuery-data()-方法 来提供对内部插件方法/设置的公共接口(同时保留 jQuery 的链式调用):
(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()的实现中从内部返回当前元素(this),jQuery链式调用就会保留,因此以下代码可以正常工作:
$("#...").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. ...     

1
这是我提供的简化版本。与之前发布的版本类似,您可以按以下方式进行调用:
$('#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);

0

这是我的做法:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

    //header
     this.header = function(object){
       console.log(object);
  }
 }

0
根据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

参考资料:链接


0
以下是一个小插件,用于调试目的的警告方法。将此代码保存在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>

0

使用defineProperty可以使其以“好”的方式工作。这里的“好”是指不必使用()来获取插件命名空间,也不必通过字符串传递函数名称。

兼容性注意事项: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链接


0

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

(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插件。我分享了一篇文章,其中讨论了从基础到高级的如何创建自己的jQuery插件。我认为你应该去看看... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/

-1
你所做的基本上是通过新方法扩展 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"); 我的朋友开始写关于插件以及如何通过功能链扩展它们的文章,这里是链接到他的博客


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接