Як створити плагін jQuery методами?


191

Я намагаюся написати плагін 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);
  }
};

Як я можу досягти чогось подібного?

Дякую!


Оновлення 18 листопада 2013 р. Я змінив правильну відповідь на відповідь наступних коментарів і відгуків Харі.

Відповіді:


310

Відповідно до сторінки написання плагінів 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 );

В основному ви зберігаєте свої функції в масиві (присвоєному функції функції обгортання) і перевіряєте запис, чи не переданий параметр є рядком, повертаючись до методу за замовчуванням (тут "init"), якщо параметр є об'єктом (або нулем).

Тоді ви можете викликати такі методи, як ...

$('div').tooltip(); // calls the init method
$('div').tooltip({  // calls the init method
  foo : 'bar'
});
$('div').tooltip('hide'); // calls the hide method
$('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method

Змінна "аргументи" Javascripts - це масив усіх переданих аргументів, тому він працює з довільною довжиною параметрів функції.


2
Це метод, який я використовую. Ви також можете статично викликати методи через $ .fn.tooltip ('ім'я методу', парами);
Граблі36

1
Дуже зручна архітектура. Я також додав цей рядок перед тим, як викликати метод init:, this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));тому тепер я можу отримати доступ до параметрів, коли захочу після ініціалізації.
ivkremer

16
Для мене, хто вперше сказав "звідки взялася змінна аргументація" - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - я використовував JS назавжди і ніколи цього не знав. Ви дізнаєтесь щось нове щодня!
streetlogics

2
@DiH, я з тобою на цьому. Такий підхід здається чудовим, але він не дає вам доступу до ваших глобальних налаштувань з будь-якого іншого місця init.
Стівен Коллінз

4
У цій техніці головна проблема! Він не створює новий екземпляр для кожного елемента в селекторі, як ви думаєте, що робите, натомість він створює лише один екземпляр, приєднаний до самого селектора. Вид мою відповідь на рішення.
Кевін Юрковський

56

Ось шаблон, який я використав для створення плагінів додатковими методами. Ви б використовували його так:

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

9
такий же візерунок, як jquery-ui, я не люблю всі магічні рядки, але чи є інший спосіб!
переосмислити

8
це здається нестандартним способом виконання справ - чи є щось простіше, ніж це, як ланцюжок функцій? спасибі!
Юваль Кармі

2
@yuval - зазвичай плагіни jQuery повертають jQuery або значення, а не сам плагін. Ось чому ім'я методу передається як аргумент до плагіна, коли потрібно викликати плагін. Ви можете передавати будь-яку кількість аргументів, але вам доведеться відрегулювати функції та аналіз аргументів. Напевно, найкраще встановити їх в анонімному об’єкті, як ви показали.
tvanfosson

1
Яке значення має ;ваш перший рядок? будь ласка, поясніть мені :)
GusDeCooL

4
@GusDeCooL це просто гарантує, що ми починаємо нову операцію, щоб наше визначення функції не трактувалося як аргумент чужому погано відформатованому Javascript (тобто початковий батьківський параметр не приймається як оператор виклику функції). Див stackoverflow.com/questions/7365172 / ...
tvanfosson

35

Як щодо цього підходу:

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.


1
Мені важко зрозуміти, як це виглядатиме. Якщо припустити, що у мене є код, який потрібно виконати при першому запуску, мені доведеться спочатку ініціалізувати його у своєму коді - приблизно так: $ ('p'). MessagePlugin (); потім пізніше в коді я хотів би викликати функцію saySomething like this $ ('p'). messagePlugin (). saySomething ('щось'); це не повторно ініціалізує плагін, а потім викликає функцію? як це виглядатиме з корпусом та параметрами? дуже тобі дякую. -юваль
Юваль Кармі

1
Хоча сортування розбиває парадигму ланцюговості jQuery.
tvanfosson

можливо, це має бути найкращою відповіддю
Dragouf

3
Кожен раз, коли ви викликаєте messagePlugin (), він створюватиме новий об'єкт із цими двома функціями, ні?
w00t

4
Основна проблема цього підходу полягає в тому, що він не може зберегти наступний ланцюжок, $('p').messagePlugin()якщо ви не викликаєте одну з двох функцій, які він повертає.
Джошуа Бамбрік

18

Проблема з обраною на даний момент відповіддю полягає в тому, що ви насправді не створюєте новий примірник спеціального плагіна для кожного елемента в селекторі, як ви думаєте, що це робите ... ви фактично створюєте лише один екземпляр і передаєте сам селектор як область застосування.

Вид цю загадку для глибшого пояснення.

Замість цього вам потрібно буде провести циклічний пошук через селектор 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);

І а робоча скрипка .

Ви помітите, як у першій скрипці всі діви завжди переміщуються вправо на таку ж кількість пікселів. Це тому, що тільки один об’єкт параметрів для всіх елементів у селекторі.

Використовуючи методику, написану вище, ви помітите, що у другій скрипці кожен div не вирівнюється і переміщується випадковим чином (за винятком першого діла, оскільки його випадковий розмір завжди встановлений на 1 у рядку 89). Це тому, що ми зараз належним чином створюємо новий екземпляр додаткового модуля для кожного елемента в селекторі. Кожен елемент має власний об'єкт параметрів і зберігається не в селекторі, а в екземплярі самого користувацького плагіна.

Це означає, що ви зможете отримати доступ до методів користувальницького плагіна, створеного на конкретному елементі в DOM, з нових селекторів jQuery, і ви не змушені будете кешувати їх, як це було б у першій скрипці.

Наприклад, це поверне масив усіх об'єктів параметрів, використовуючи техніку у другій скрипці. Він повернеться невизначеним у першому.

$('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 Ви також можете спростити частину свого коду, використовуючи анонімні методи.
dalemac

Застосування jQuery не працює за допомогою цього методу $('.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 значно спростив це завдяки впровадженню фабрики віджетів .

Приклад:

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


@ daniel.sedlacek а) "дуже погана архітектура" - це стандартна архітектура віджетів jQuery b) "перевірена цілісність під час компіляції" - JavaScript - це динамічна мова c) "TypeScript" - ким?
Ярін

а) це аргумент рекламної популяції, б) кожен кращий JS IDE має завершення чи вкладений код, в) google
daniel.sedlacek

Це чиста манія, містер Седласек.
mystrdat

За документами: Ця система називається Widget Factory і виставляється як jQuery.widget як частина jQuery UI 1.8; однак, його можна використовувати незалежно від інтерфейсу jQuery. Як використовується $ .widget без інтерфейсу jQuery?
Airn5475

13

Більш простий підхід - використовувати вкладені функції. Тоді ви можете зав'язати їх ланцюжком об'єктно-орієнтовано. Приклад:

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", якщо вам потрібно посилання на екземпляр у виклику клієнта. Ви не можете просто повернути "це" у вкладеній функції, оскільки це поверне посилання на функцію, а не на екземпляр jQuery. Повернення посилання jQuery дозволяє ланцюжком внутрішніх методів jQuery при поверненні.


2
Це чудово - мені цікаво лише, чому, схоже, jQuery надає перевагу виклику методів на ім'я, як у шаблоні .plugin ('method')?
w00t

6
Це не працює. Якщо ви запустите плагін у двох різних контейнерах, внутрішні змінні будуть переосмислені (а саме _this)
mbrochh

Помилка: не дозволяє pluginContainer.MyPlugin.DoEvenMore (). DoSomething ();
Пол Швець

9

Я отримав його від 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
Alex G

@AlexG дав цей приклад ви б додати return $elementце в цьому прикладі ви б змінити його plugin.foo_public_method = function() {/* Your Code */ return $element;}@Salim спасибі за допомогу мені ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS

6

Занадто пізно, але, можливо, це може допомогти комусь одного дня.

Я опинився в такій самій ситуації, як створити плагін 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-learn-create-a-jquery-plugin-part-i / ).


можливо найкращий пост, який я натрапив ще на тему створення плагінів jQuery як для початківців - спасибі;)
Dex Dave

5

Ви можете зробити:

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

3

Що з використанням тригерів? Хтось знає якісь недоліки, використовуючи їх? Перевага полягає в тому, що всі внутрішні змінні доступні через тригери, а код дуже простий.

Дивіться на 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>');
        }

    });

}

1
пор. ваш коментар. Єдина проблема, яку я тут бачу, - це, мабуть, неправильне використання системи подій. Нетипово використовувати події виключно для виклику функції; це здається завищеним і може бути легко зламано. Зазвичай ви використовуєте події способом публікації та підписки, наприклад, функція публікує, що сталася якась умова "А". Інші суб'єкти, зацікавлені у "А", слухають повідомлення про те, що "А" сталося, а потім щось роблять. Ви, здається, використовуєте це як "push" команду замість цього, але припускаючи, що є лише один слухач. Ви хочете бути обережними, щоб ваша семантика не була порушена (іншими), додаючи слухачів.
tvanfosson

@tvanfosson Дякуємо за ваш коментар. Я розумію, що це не звичайна техніка, і вона може викликати проблеми, якщо хтось випадково додасть слухача події, але якщо він названий на честь плагіна, то це дуже малоймовірно. Я не знаю жодних проблем, пов’язаних із продуктивністю, але сам код здається мені набагато простішим, ніж з іншими рішеннями, але мені може щось не вистачати.
István Ujj-Mészáros

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 наступного рівня. ми очікуємо від вашої потрібної відповіді.
Сакті Картік

Здрастуйте @SakthiKarthik, Off curce Незабаром я опублікую новий підручник у своєму блозі
Gopal Joshi

1
Привіт @SakthiKarthik, Ви можете посилатися на нову статтю про плагін jquery наступного рівня тут sgeek.org/…
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

Ось моя версія голих кісток цього. Подібно до раніше розміщених, ви б закликали:

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

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()jQuery-ланцюжка буде збережена - значить, наступні роботи:

$("#...").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. ...     

0

Це насправді може бути змушене працювати "приємним" способом, використовуючи defineProperty. Де "nice" означає, не використовуючи ()для отримання простору імен плагінів і не потрібно передавати ім'я функції за рядком.

Нітка сумісності: defineProperty не працює в старовинних браузерах, таких як IE8 і нижче. Caveat: $.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

Відповідно до стандарту 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

Я думаю, що це може допомогти вам ...

(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. Я поділився статтею, в якій я обговорював, як створити свій власний плагін jQuery від Basic до Advance. Я думаю, ви повинні перевірити це ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/


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

Ось як я це роблю:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

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

-2

Що ви зробили, це в основному розширення об’єкта 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 ("привіт"); Мій друг, він почав писати про доходи і про те, як поширити їх на ваш функціонал, ось посилання на його блог

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.