Làm cách nào để tạo một plugin jQuery bằng các phương thức?


191

Tôi đang cố gắng viết một plugin jQuery sẽ cung cấp các hàm / phương thức bổ sung cho đối tượng gọi nó. Tất cả các hướng dẫn tôi đọc trực tuyến (đã duyệt trong 2 giờ qua) bao gồm, nhiều nhất là cách thêm tùy chọn, nhưng không phải chức năng bổ sung.

Đây là những gì tôi đang tìm cách làm:

// định dạng div thành một thùng chứa thư bằng cách gọi plugin cho div đó

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

Hoặc một cái gì đó dọc theo các đường dây. Đây là những gì nó hiểu được: Tôi gọi plugin, sau đó tôi gọi một chức năng liên quan đến plugin đó. Tôi dường như không thể tìm ra cách để làm điều này và tôi đã thấy nhiều plugin làm điều đó trước đây.

Đây là những gì tôi có cho đến nay cho plugin:

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

Làm thế nào tôi có thể đạt được một cái gì đó như thế?

Cảm ơn bạn!


Cập nhật ngày 18 tháng 11 năm 2013: Tôi đã thay đổi câu trả lời chính xác cho câu trả lời và nhận xét sau của Hari.

Câu trả lời:


310

Theo trang Tác giả Trình cắm jQuery ( http://docs.jquery.com/Plugins/Authoring ), tốt nhất không nên làm rối các không gian tên của jQuery và jQuery.fn. Họ đề xuất phương pháp này:

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

Về cơ bản, bạn lưu trữ các hàm của mình trong một mảng (nằm trong hàm gói) và kiểm tra một mục nhập nếu tham số được truyền là một chuỗi, trở lại một phương thức mặc định ("init" ở đây) nếu tham số là một đối tượng (hoặc null).

Sau đó, bạn có thể gọi các phương thức như vậy ...

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

Biến "đối số" của Javascripts là một mảng gồm tất cả các đối số được truyền để nó hoạt động với độ dài tùy ý của các tham số hàm.


2
Đây là phương pháp tôi sử dụng. Bạn cũng có thể gọi các phương thức một cách tĩnh thông qua $ .fn.tooltip ('methodname', params);
Rake36

1
Kiến trúc rất tiện dụng. Tôi cũng đã thêm dòng này trước khi gọi phương thức init: this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));vì vậy bây giờ tôi có thể truy cập vào các tùy chọn bất cứ khi nào tôi muốn sau khi khởi tạo.
ivkremer

16
Đối với bất kỳ ai như tôi, người đầu tiên đã nói "biến đối số đến từ đâu" - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/, - Tôi đã sử dụng JS mãi mãi và không bao giờ biết điều đó. Bạn học được điều gì mới mỗi ngày!
streetlogics

2
@DiH, tôi với bạn về điều này. Cách tiếp cận này có vẻ tuyệt vời, nhưng nó không cung cấp cho bạn quyền truy cập vào các cài đặt toàn cầu của bạn từ bất kỳ nơi nào khác ngoài init.
Stephen Collins

4
Có một vấn đề lớn với kỹ thuật này! Nó không tạo ra một thể hiện mới cho mọi phần tử trong bộ chọn như bạn nghĩ bạn đang làm, thay vào đó nó chỉ tạo một thể hiện duy nhất được gắn vào chính bộ chọn. Xem câu trả lời của tôi cho một giải pháp.
Kevin Jurkowski

56

Đây là mẫu tôi đã sử dụng để tạo plugin với các phương thức bổ sung. Bạn sẽ sử dụng nó như:

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

hoặc, để gọi một phương thức trực tiếp,

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

Thí dụ:

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

9
cùng một mô hình như jquery-ui, tôi không thích tất cả các chuỗi ma thuật nhưng có cách nào khác không!
redsapes

8
điều này có vẻ như là một cách làm việc không chuẩn - có gì đơn giản hơn thế này, như các chuỗi chức năng không? cảm ơn bạn!
Yuval Karmi

2
@yuval - Các plugin jQuery thường trả về jQuery hoặc một giá trị, không phải chính plugin đó. Đó là lý do tại sao tên của phương thức được truyền dưới dạng đối số cho plugin khi bạn muốn gọi plugin. Bạn có thể vượt qua bất kỳ số lượng đối số, nhưng bạn sẽ phải điều chỉnh các chức năng và phân tích cú pháp đối số. Có lẽ tốt nhất để đặt chúng trong một đối tượng ẩn danh như bạn đã chỉ ra.
tvanfosson

1
Ý nghĩa của ;dòng đầu tiên của bạn là gì? vui lòng giải thích cho tôi :)
GusDeCooL

4
@GusDeCooL chỉ cần đảm bảo rằng chúng tôi đang bắt đầu một câu lệnh mới để định nghĩa hàm của chúng tôi không bị hiểu là một đối số với Javascript được định dạng kém của người khác (nghĩa là paren ban đầu không được coi là toán tử gọi hàm). Xem stackoverflow.com/questions/7365172/ Mạnh
tvanfosson

35

Điều gì về phương pháp này:

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

Các đối tượng được chọn được lưu trữ trong bao đóng messagePlugin và hàm đó trả về một đối tượng có chứa các hàm được liên kết với plugin, trong mỗi chức năng bạn có thể thực hiện các hành động mong muốn cho các đối tượng hiện được chọn.

Bạn có thể kiểm tra và chơi với mã ở đây .

Chỉnh sửa: Mã được cập nhật để bảo vệ sức mạnh của chuỗi jQuery.


1
tôi có một chút khó khăn để hiểu những gì nó sẽ trông như thế nào. Giả sử tôi có mã cần được thực thi trong lần chạy đầu tiên, trước tiên tôi sẽ phải khởi tạo nó trong mã của mình - đại loại như thế này: $ ('p'). MessagePlugin (); sau đó trong mã tôi muốn gọi hàm sayS Something like this $ ('p'). messagePlugin (). sayS Something ('Something'); Điều này sẽ không khởi tạo lại plugin và sau đó gọi hàm? Điều này sẽ trông như thế nào với bao vây và các tùy chọn? Cảm ơn rât nhiều. -yuval
Yuval Karmi

1
Mặc dù vậy, sắp xếp các mô hình phá vỡ chuỗi của jQuery.
tvanfosson

có lẽ đây sẽ là câu trả lời hay nhất
Dragouf

3
Mỗi khi bạn gọi messagePlugin () nó sẽ tạo một đối tượng mới với hai hàm đó, phải không?
w00t

4
Vấn đề chính với cách tiếp cận này là nó không thể duy trì khả năng theo chuỗi $('p').messagePlugin()trừ khi bạn gọi một trong hai chức năng mà nó trả về.
Joshua Bambrick

18

Vấn đề với câu trả lời hiện được chọn là bạn không thực sự tạo một phiên bản mới của plugin tùy chỉnh cho mọi thành phần trong bộ chọn như bạn nghĩ bạn đang làm ... thực tế bạn chỉ tạo một phiên bản duy nhất và chuyển vào bộ chọn chính là phạm vi.

Xem fiddle này để giải thích sâu hơn.

Thay vào đó, bạn sẽ cần lặp qua bộ chọn bằng jQuery.each và khởi tạo một phiên bản mới của plugin tùy chỉnh cho mọi thành phần trong bộ chọn.

Đây là cách thực hiện:

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

Và một fiddle làm việc .

Bạn sẽ nhận thấy làm thế nào trong câu đố đầu tiên, tất cả các div luôn được di chuyển sang bên phải cùng số pixel chính xác. Đó là bởi vì chỉ có một đối tượng tùy chọn tồn tại cho tất cả các thành phần trong bộ chọn.

Sử dụng kỹ thuật được viết ở trên, bạn sẽ nhận thấy rằng trong fiddle thứ hai, mỗi div không được căn chỉnh và được di chuyển ngẫu nhiên (không bao gồm div đầu tiên vì nó ngẫu nhiên luôn được đặt thành 1 trên dòng 89). Đó là bởi vì chúng tôi hiện đang khởi tạo chính xác một phiên bản plugin tùy chỉnh mới cho mọi thành phần trong bộ chọn. Mỗi phần tử có đối tượng tùy chọn riêng và không được lưu trong bộ chọn, nhưng trong trường hợp của chính plugin tùy chỉnh.

Điều này có nghĩa là bạn sẽ có thể truy cập các phương thức của plugin tùy chỉnh được khởi tạo trên một phần tử cụ thể trong DOM từ các bộ chọn jQuery mới và không bị buộc phải lưu trữ chúng, như bạn sẽ ở trong câu đố đầu tiên.

Ví dụ, điều này sẽ trả về một mảng của tất cả các đối tượng tùy chọn bằng cách sử dụng kỹ thuật trong câu đố thứ hai. Nó sẽ trở lại không xác định trong lần đầu tiên.

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

Đây là cách bạn sẽ phải truy cập vào đối tượng tùy chọn trong fiddle đầu tiên và sẽ chỉ trả về một đối tượng duy nhất, không phải là một mảng của chúng:

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

Tôi khuyên bạn nên sử dụng kỹ thuật trên, không phải từ câu trả lời hiện được chọn.


Cảm ơn, điều này đã giúp tôi rất nhiều, đặc biệt là giới thiệu phương thức .data () cho tôi. Rất tiện dụng. FWIW bạn cũng có thể đơn giản hóa một số mã của mình bằng các phương thức ẩn danh.
dalemac

jQuery chainability không hoạt động sử dụng phương pháp này ... $('.my-elements').find('.first-input').customPlugin('update'‌​, 'first value').end().find('.second-input').customPlugin('update', 'second value'); returns Cannot read property 'end' of undefined. jsfiddle.net/h8v1k2pL
Alex G

16

jQuery đã làm điều này dễ dàng hơn rất nhiều với việc giới thiệu Widget Factory .

Thí dụ:

$.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 ) {
        // ...
    }

});

Khởi tạo:

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

Phương thức gọi:

$('#my-element').myPlugin('myPublicMethod', 20);

(Đây là cách thư viện UI UI được xây dựng.)


@ daniel.sedlacek a) "kiến trúc rất tệ" - đó là kiến ​​trúc widget tiêu chuẩn của jQuery b) "đã kiểm tra tính toàn vẹn tại thời gian biên dịch" - JavaScript là ngôn ngữ động c) "TypeScript" - wha?
Yarin

a) đó là đối tượng quảng cáo đối số, b) mỗi IDE IDE tốt hơn đều có mã hoàn thành hoặc linting, c) google nó
daniel.sedlacek

Đó là ảo tưởng thuần túy, ông Sedlacek.
mystrdat

Per docs: Hệ thống này được gọi là Widget Factory và được hiển thị dưới dạng jQuery.widget như một phần của jQuery UI 1.8; tuy nhiên, nó có thể được sử dụng độc lập với jQuery UI. $ .Widget được sử dụng mà không có giao diện người dùng jQuery như thế nào?
Airn5485

13

Một cách tiếp cận đơn giản hơn là sử dụng các hàm lồng nhau. Sau đó, bạn có thể xâu chuỗi chúng theo cách hướng đối tượng. Thí dụ:

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

Và đây là cách gọi nó:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();

Hãy cẩn thận. Bạn không thể gọi một hàm lồng nhau cho đến khi nó được tạo. Vì vậy, bạn không thể làm điều này:

var pluginContainer = $("#divSomeContainer");
pluginContainer.MyPlugin();
pluginContainer.MyPlugin.DoSomething.DoEvenMore();
pluginContainer.MyPlugin.DoSomething();

Hàm DoEvenMore thậm chí không tồn tại vì chức năng DoS Something chưa được chạy mà cần phải tạo chức năng DoEvenMore. Đối với hầu hết các plugin jQuery, bạn thực sự sẽ chỉ có một cấp hàm được lồng chứ không phải hai cấp như tôi đã trình bày ở đây.
Chỉ cần đảm bảo rằng khi bạn tạo các hàm lồng nhau mà bạn xác định các hàm này ở đầu hàm cha của chúng trước khi bất kỳ mã nào khác trong hàm cha được thực thi.

Cuối cùng, lưu ý rằng thành viên "này" được lưu trữ trong một biến có tên là "_this". Đối với các hàm lồng nhau, bạn nên trả về "_this" nếu bạn cần một tham chiếu đến thể hiện trong ứng dụng khách gọi. Bạn không thể chỉ trả về "cái này" trong hàm lồng nhau bởi vì điều đó sẽ trả về một tham chiếu đến hàm chứ không phải đối tượng jQuery. Trả về một tham chiếu jQuery cho phép bạn quay lại các phương thức jQuery nội tại khi trả về.


2
Điều này thật tuyệt - tôi chỉ tự hỏi tại sao jQuery dường như thích gọi các phương thức theo tên như trong mẫu .plugin ('phương thức')?
w00t

6
Điều này không hoạt động. Nếu bạn gọi plugin trên hai thùng chứa khác nhau, các biến nội bộ sẽ bị ghi đè (cụ thể là
_this

Fail: không cho phép pluginContainer.MyPlugin.DoEvenMore (). DoS Something ();
Paul Swetz

9

Tôi đã nhận nó từ jQuery Boilerplate

Cũng được mô tả trong jQuery Boilerplate, tiếp tục

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

Phương thức của bạn phá vỡ chuỗi xích jQuery: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);trả về Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G

@AlexG đã đưa ra ví dụ này, bạn sẽ thêm return $elementvào trong ví dụ này, bạn sẽ đổi nó thành plugin.foo_public_method = function() {/* Your Code */ return $element;}@Salim cảm ơn vì đã giúp tôi ... github.com/AndreaLombardo/BootSideMothy/pull 432
CrandellWS

6

Quá muộn nhưng có thể nó sẽ giúp ai đó một ngày nào đó.

Tôi đã ở trong tình huống tương tự như, tạo một plugin jQuery với một số phương thức và sau khi đọc một số bài viết và một số lốp xe, tôi tạo một trình soạn thảo plugin jQuery ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ).

Ngoài ra, tôi phát triển cùng với nó một plugin để quản lý thẻ ( https://github.com/acanimal/tagger.js ) và viết hai bài đăng blog giải thích từng bước tạo plugin jQuery ( http: // acquilanimal. com / blog / 2013/01/15 / Things-i-learn-created-a-jquery-plugin-part-i / ).


có thể là bài viết hay nhất mà tôi đã bắt gặp về việc tạo các trình cắm jQuery khi mới bắt đầu - cảm ơn;)
Dex Dave

5

Bạn có thể làm:

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

Theo cách này, đối tượng plugin của bạn được lưu trữ dưới dạng giá trị dữ liệu trong phần tử của bạn.

//Initialization without option
$('#myId').yourPlugin();

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

// call show method
$('#myId').yourPlugin('show');

3

Điều gì về việc sử dụng kích hoạt? Có ai biết bất kỳ nhược điểm sử dụng chúng? Lợi ích là tất cả các biến nội bộ có thể truy cập thông qua các kích hoạt và mã rất đơn giản.

Xem trên jsfiddle .

Ví dụ sử dụng

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

Cắm vào

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>');
        }

    });

}

1
xem bình luận của bạn. Vấn đề duy nhất tôi thấy ở đây được cho là lạm dụng hệ thống sự kiện. Thật không điển hình khi sử dụng các sự kiện hoàn toàn để gọi một hàm; nó có vẻ như quá mức cần thiết và có thể dễ dàng bị phá vỡ. Thông thường, bạn sẽ sử dụng các sự kiện theo kiểu đăng ký xuất bản, ví dụ: một hàm xuất bản rằng một số điều kiện "A" đã xảy ra. Các thực thể khác, quan tâm đến "A", lắng nghe thông báo rằng "A" đã xảy ra, sau đó làm một cái gì đó. Thay vào đó, bạn dường như đang sử dụng nó như một "lệnh" đẩy, nhưng giả sử chỉ có một người nghe. Bạn muốn cẩn thận rằng ngữ nghĩa của bạn không bị phá vỡ bởi (những người khác) thêm người nghe.
tvanfosson

@tvanfosson Cảm ơn bình luận của bạn. Tôi hiểu rằng đó không phải là kỹ thuật phổ biến và nó có thể gây ra sự cố nếu ai đó vô tình thêm người nghe sự kiện, nhưng nếu nó được đặt tên theo plugin, thì điều đó rất khó xảy ra. Tôi không biết về bất kỳ vấn đề nào liên quan đến hiệu suất, nhưng bản thân mã dường như đơn giản hơn nhiều so với các giải pháp khác, nhưng tôi có thể đang thiếu một cái gì đó.
István Ujj-Mészáros

3

Ở đây tôi muốn đề xuất các bước để tạo plugin đơn giản với các đối số.

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

Ở đây, chúng tôi đã thêm đối tượng mặc định được gọi paramsvà đặt giá trị mặc định của các tùy chọn bằng cách sử dụngextend hàm. Do đó, nếu chúng ta chuyển đối số trống thì nó sẽ đặt giá trị mặc định thay vì nó sẽ đặt.

Đọc thêm: Cách tạo plugin JQuery


Xin chào Gopal Joshi, Vui lòng cung cấp plugin jquery cấp độ tiếp theo. chúng tôi mong đợi từ câu trả lời cần thiết của bạn.
Sakthi Karthik

Xin chào @SakthiKarthik, Tắt nguồn Tôi sẽ sớm xuất bản hướng dẫn mới trong blog của mình
Gopal Joshi

1
Xin chào @SakthiKarthik, Bạn có thể tham khảo bài viết mới về plugin jquery cấp độ tiếp theo tại đây sgeek.org/iêu
Gopal Joshi

2

Hãy thử cái này:

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

Đây là phiên bản xương trần của tôi về điều này. Tương tự như những người được đăng trước đó, bạn sẽ gọi như:

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

-Hoặc truy cập trực tiếp vào ví dụ @ 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);

1

Plugin-cấu trúc sau đây sử dụng các jQuery- data()-method để cung cấp một giao diện công cộng để plugin phương pháp nội bộ / -settings (trong khi vẫn giữ 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));

Bây giờ bạn có thể gọi các phương thức plugin nội bộ để truy cập hoặc sửa đổi dữ liệu plugin hoặc thành phần có liên quan bằng cú pháp này:

$("#...").data('myPlugin').myPublicPluginMethod(); 

Miễn là bạn trả lại phần tử hiện tại (cái này) từ bên trong việc triển khai chuỗi myPublicPluginMethod()jQuery của bạn sẽ được giữ nguyên - vì vậy các công việc sau:

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

Dưới đây là một số ví dụ (để biết chi tiết kiểm tra fiddle này ):

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

0

Điều này thực sự có thể được thực hiện để làm việc theo cách "tốt đẹp" bằng cách sử dụng defineProperty. Trong đó "đẹp" có nghĩa là không phải sử dụng ()để có được không gian tên plugin cũng như không phải truyền tên hàm theo chuỗi.

Khả năng tương thích nit: defineProperty không hoạt động trong các trình duyệt cổ như IE8 trở xuống. Hãy cẩn thận: $.fn.color.blue.apply(foo, args) sẽ không hoạt động, bạn cần sử dụng 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();

Liên kết JSFiddle


0

Theo tiêu chuẩn jquery, bạn có thể tạo plugin như sau:

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

Làm thế nào để gọi plugin này?

1.$('your element').loadKeywords('show',{'callback':callbackdata,'keyName':'myKey'}); // show() will be called

Tham khảo: liên kết


0

Tôi nghĩ rằng điều này có thể giúp bạn ...

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

Trong ví dụ trên tôi đã tạo ra một plugin nổi bật jquery đơn giản. Tôi đã chia sẻ một bài viết trong đó tôi đã thảo luận về Cách tạo Plugin jQuery của riêng bạn từ Basic đến Advance. Tôi nghĩ bạn nên kiểm tra xem ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/


0

Sau đây là một trình cắm nhỏ để có phương thức cảnh báo cho mục đích gỡ lỗi. Giữ mã này trong tệp 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

Đây là cách tôi làm điều đó:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

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

-2

Những gì bạn đã làm về cơ bản là mở rộng đối tượng jQuery.fn.messagePlugin bằng phương thức mới. Đó là hữu ích nhưng không phải trong trường hợp của bạn.

Bạn phải làm là sử dụng kỹ thuật này

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

};

Nhưng bạn có thể thực hiện những gì bạn muốn Tôi có nghĩa là có một cách để làm $ ("# mydiv"). MessagePlugin (). SayS Something ("xin chào"); Bạn tôi, anh ấy bắt đầu viết về lugins và cách mở rộng chúng với chuỗi chức năng của bạn ở đây là liên kết đến blog của anh ấy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.