Wie erstelle ich ein jQuery-Plugin mit Methoden?


191

Ich versuche, ein jQuery-Plugin zu schreiben, das dem Objekt, das es aufruft, zusätzliche Funktionen / Methoden bietet. Alle Tutorials, die ich online gelesen habe (die ich in den letzten 2 Stunden durchsucht habe), enthalten höchstens das Hinzufügen von Optionen, jedoch keine zusätzlichen Funktionen.

Folgendes möchte ich tun:

// formatiere div als Nachrichtencontainer, indem du das Plugin für dieses div aufrufst

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

oder so ähnlich. Es läuft darauf hinaus: Ich rufe das Plugin auf und rufe dann eine Funktion auf, die diesem Plugin zugeordnet ist. Ich kann anscheinend keinen Weg finden, dies zu tun, und ich habe schon viele Plugins gesehen, die dies getan haben.

Folgendes habe ich bisher für das 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);
  }
};

Wie kann ich so etwas erreichen?

Danke dir!


Update 18. November 2013: Ich habe die richtige Antwort auf die folgenden Kommentare und Upvotes von Hari geändert.

Antworten:


310

Laut der Authoring-Seite des jQuery-Plugins ( http://docs.jquery.com/Plugins/Authoring ) ist es am besten, die Namespaces jQuery und jQuery.fn nicht zu verwirren. Sie schlagen diese Methode vor:

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

Grundsätzlich speichern Sie Ihre Funktionen in einem Array (für die Wrapping-Funktion) und suchen nach einem Eintrag, wenn der übergebene Parameter eine Zeichenfolge ist. Wenn der Parameter ein Objekt (oder null) ist, kehren Sie zu einer Standardmethode (hier "init") zurück.

Dann können Sie die Methoden so aufrufen ...

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

Die Variable "Argumente" von Javascripts ist ein Array aller übergebenen Argumente, sodass sie mit beliebigen Längen von Funktionsparametern funktioniert.


2
Dies ist die Methode, die ich benutze. Sie können die Methoden auch statisch über $ .fn.tooltip ('Methodenname', Parameter) aufrufen.
Rake36

1
Sehr handliche Architektur. Ich habe diese Zeile auch hinzugefügt, bevor ich die init-Methode aufgerufen habe: this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));Jetzt kann ich nach der Initialisierung jederzeit auf Optionen zugreifen.
ivkremer

16
Für alle wie mich, die zuerst sagten "Woher kommt die Argumentvariable?" - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Ich habe JS für immer verwendet und das nie gewusst. Sie lernen jeden Tag etwas Neues!
Streetlogics

2
@ DiH, ich bin mit dir in diesem Fall. Dieser Ansatz scheint großartig zu sein, bietet Ihnen jedoch keinen Zugriff auf Ihre globalen Einstellungen von einem anderen Ort als init.
Stephen Collins

4
Es gibt ein großes Problem mit dieser Technik! Es wird nicht für jedes Element im Selektor eine neue Instanz erstellt, wie Sie glauben, sondern nur eine einzige Instanz, die an den Selektor selbst angehängt ist. Sehen Sie sich meine Antwort für eine Lösung an.
Kevin Jurkowski

56

Hier ist das Muster, das ich zum Erstellen von Plugins mit zusätzlichen Methoden verwendet habe. Sie würden es wie folgt verwenden:

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

oder, um eine Methode direkt aufzurufen,

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

Beispiel:

;(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
das gleiche Muster wie jquery-ui, ich mag nicht alle magischen Saiten, aber gibt es einen anderen Weg!
Redsquare

8
Dies scheint eine nicht standardmäßige Vorgehensweise zu sein. Gibt es etwas Einfacheres als Verkettungsfunktionen? Danke!
Yuval Karmi

2
@yuval - Normalerweise geben jQuery-Plugins jQuery oder einen Wert zurück, nicht das Plugin selbst. Aus diesem Grund wird der Name der Methode als Argument an das Plugin übergeben, wenn Sie das Plugin aufrufen möchten. Sie können beliebig viele Argumente übergeben, müssen jedoch die Funktionen und die Argumentanalyse anpassen. Am besten setzen Sie sie in ein anonymes Objekt, wie Sie gezeigt haben.
Tvanfosson

1
Was bedeutet das ;in Ihrer ersten Zeile? Bitte erklären Sie mir :)
GusDeCooL

4
@GusDeCooL stellt nur sicher, dass wir eine neue Anweisung starten, damit unsere Funktionsdefinition nicht als Argument für das schlecht formatierte Javascript eines anderen interpretiert wird (dh der anfängliche Paren wird nicht als Funktionsaufrufoperator verwendet). Siehe stackoverflow.com/questions/7365172/…
tvanfosson

35

Was ist mit diesem Ansatz:

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

Die ausgewählten Objekte werden im messagePlugin-Abschluss gespeichert, und diese Funktion gibt ein Objekt zurück, das die mit dem Plugin verknüpften Funktionen enthält. In jeder Funktion können Sie die gewünschten Aktionen für die aktuell ausgewählten Objekte ausführen.

Sie können mit dem Code testen und spielen hier .

Bearbeiten: Der Code wurde aktualisiert, um die Leistungsfähigkeit der jQuery-Verkettbarkeit zu erhalten.


1
Es fällt mir ein bisschen schwer zu verstehen, wie das aussehen würde. Angenommen, ich habe Code, der beim ersten Ausführen ausgeführt werden muss, muss ich ihn zuerst in meinem Code initialisieren - ungefähr so: $ ('p'). MessagePlugin (); dann später im Code möchte ich die Funktion saySomething wie dieses $ ('p'). messagePlugin (). saySomething ('etwas') aufrufen; Wird das Plugin dadurch nicht neu initialisiert und dann die Funktion aufgerufen? Wie würde dies mit dem Gehäuse und den Optionen aussehen? vielen Dank. -yuval
Yuval Karmi

1
Dies bricht jedoch das Verkettbarkeitsparadigma von jQuery.
Tvanfosson

Vielleicht sollte dies die beste Antwort sein
Dragouf

3
Jedes Mal, wenn Sie messagePlugin () aufrufen, wird ein neues Objekt mit diesen beiden Funktionen erstellt, nicht wahr?
w00t

4
Das Hauptproblem bei diesem Ansatz besteht darin, dass die Kettenfähigkeit nur dann erhalten bleiben kann, $('p').messagePlugin()wenn Sie eine der beiden zurückgegebenen Funktionen aufrufen.
Joshua Bambrick

18

Das Problem mit der aktuell ausgewählten Antwort besteht darin, dass Sie nicht für jedes Element in der Auswahl eine neue Instanz des benutzerdefinierten Plugins erstellen, wie Sie denken ... Sie erstellen tatsächlich nur eine einzelne Instanz und übergeben sie der Selektor selbst als Bereich.

Sehen Sie sich diese Geige für eine tiefere Erklärung an.

Stattdessen müssen Sie den Selektor mit jQuery.each durchlaufen und für jedes Element im Selektor eine neue Instanz des benutzerdefinierten Plugins instanziieren.

Hier ist wie:

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

Und eine funktionierende Geige .

Sie werden feststellen, dass in der ersten Geige alle Divs immer genau die gleiche Anzahl von Pixeln nach rechts verschoben werden. Dies liegt daran , dass für alle Elemente im Selektor nur ein Optionsobjekt vorhanden ist.

Wenn Sie die oben beschriebene Technik verwenden, werden Sie feststellen, dass in der zweiten Geige nicht jedes Div ausgerichtet und zufällig verschoben wird (mit Ausnahme des ersten Div, da der Randomizer in Zeile 89 immer auf 1 gesetzt ist). Das liegt daran, dass wir jetzt für jedes Element im Selektor eine neue benutzerdefinierte Plugin-Instanz ordnungsgemäß instanziieren. Jedes Element hat ein eigenes Optionsobjekt und wird nicht im Selektor gespeichert, sondern im Fall des benutzerdefinierten Plugins.

Dies bedeutet, dass Sie über neue jQuery-Selektoren auf die Methoden des benutzerdefinierten Plugins zugreifen können, die für ein bestimmtes Element im DOM instanziiert wurden, und nicht gezwungen sind, sie wie in der ersten Geige zwischenzuspeichern.

Dies würde beispielsweise ein Array aller Optionsobjekte unter Verwendung der Technik in der zweiten Geige zurückgeben. Es würde im ersten undefiniert zurückkehren.

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

Auf diese Weise müssten Sie in der ersten Geige auf das Optionsobjekt zugreifen und nur ein einzelnes Objekt zurückgeben, kein Array davon:

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

Ich würde vorschlagen, die obige Technik zu verwenden, nicht die aus der aktuell ausgewählten Antwort.


Vielen Dank, das hat mir sehr geholfen, insbesondere die Einführung der .data () -Methode. Sehr praktisch. FWIW können Sie auch einen Teil Ihres Codes mithilfe anonymer Methoden vereinfachen.
Dalemac

jQuery Verkettbarkeit nicht funktioniert diese Methode verwenden ... $('.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 hat dies mit der Einführung der Widget Factory erheblich vereinfacht .

Beispiel:

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

});

Initialisierung:

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

Methodenaufruf:

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

(So ​​wird die jQuery-UI- Bibliothek erstellt.)


@ daniel.sedlacek a) "sehr schlechte Architektur" - es ist die Standard-Widget-Architektur von jQuery b) "beim Kompilieren auf Integrität überprüft" - JavaScript ist eine dynamische Sprache c) "TypeScript" - was?
Yarin

a) das ist argumentum ad populum, b) jede bessere JS IDE hat Code-Vervollständigung oder Flusen, c) google es
daniel.sedlacek

Das ist reine Täuschung, Mr. Sedlacek.
Mystrdat

Pro Dokument: Dieses System heißt Widget Factory und wird als Teil von jQuery UI 1.8 als jQuery.widget verfügbar gemacht. Es kann jedoch unabhängig von der jQuery-Benutzeroberfläche verwendet werden. Wie wird $ .widget ohne jQuery-Benutzeroberfläche verwendet?
Airn5475

13

Ein einfacherer Ansatz ist die Verwendung verschachtelter Funktionen. Dann können Sie sie objektorientiert verketten. Beispiel:

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

Und so nennt man es:

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

Sei aber vorsichtig. Sie können eine verschachtelte Funktion erst aufrufen, wenn sie erstellt wurde. Sie können dies also nicht tun:

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

Die DoEvenMore-Funktion existiert nicht einmal, da die DoSomething-Funktion noch nicht ausgeführt wurde, die zum Erstellen der DoEvenMore-Funktion erforderlich ist. Für die meisten jQuery-Plugins haben Sie wirklich nur eine Ebene verschachtelter Funktionen und nicht zwei, wie ich hier gezeigt habe.
Stellen Sie einfach sicher, dass Sie beim Erstellen verschachtelter Funktionen diese Funktionen am Anfang ihrer übergeordneten Funktion definieren, bevor ein anderer Code in der übergeordneten Funktion ausgeführt wird.

Beachten Sie schließlich, dass das Element "this" in einer Variablen namens "_this" gespeichert ist. Für verschachtelte Funktionen sollten Sie "_this" zurückgeben, wenn Sie einen Verweis auf die Instanz im aufrufenden Client benötigen. Sie können "this" nicht einfach in der verschachtelten Funktion zurückgeben, da dadurch ein Verweis auf die Funktion und nicht auf die jQuery-Instanz zurückgegeben wird. Durch die Rückgabe einer jQuery-Referenz können Sie intrinsische jQuery-Methoden bei der Rückgabe verketten.


2
Das ist großartig - ich frage mich nur, warum jQuery es bevorzugt, die Methoden wie im .plugin-Muster ('method') beim Namen zu nennen.
w00t

6
Das funktioniert nicht. Wenn Sie das Plugin für zwei verschiedene Container aufrufen, werden die internen Variablen überschrieben (nämlich _this)
mbrochh

Fehler: erlaubt nicht pluginContainer.MyPlugin.DoEvenMore (). DoSomething ();
Paul Swetz

9

Ich habe es von jQuery Plugin Boilerplate bekommen

Auch in jQuery Plugin Boilerplate beschrieben, 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);

Ihre Methode bricht jQuery Verkettung: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);gibt Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G

@AlexG gegeben dieses Beispiel würden Sie hinzufügen, return $elementso dass Sie es in diesem Beispiel in plugin.foo_public_method = function() {/* Your Code */ return $element;}@Salim ändern würden, danke, dass Sie mir geholfen haben ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS

6

Zu spät, aber vielleicht kann es eines Tages jemandem helfen.

Ich war in der gleichen Situation wie beim Erstellen eines jQuery-Plugins mit einigen Methoden, und nachdem ich einige Artikel und einige Reifen gelesen hatte, erstellte ich ein jQuery-Plugin-Boilerplate ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ).

Außerdem entwickle ich damit ein Plugin zum Verwalten von Tags ( https://github.com/acanimal/tagger.js ) und schreibe zwei Blog-Beiträge, in denen Schritt für Schritt die Erstellung eines jQuery-Plugins ( http: // acuriousanimal) erläutert wird. com / blog / 2013/01/15 / Dinge, die ich gelernt habe, ein jquery-Plugin-Teil-i zu erstellen / ).


Möglicherweise der beste Beitrag, den ich bisher über das Erstellen von jQuery-Plugins als Anfänger gefunden habe - danke;)
Dex Dave

5

Du kannst tun:

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

Auf diese Weise wird Ihr Plugins-Objekt als Datenwert in Ihrem Element gespeichert.

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

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

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

3

Was ist mit Triggern? Kennt jemand einen Nachteil bei der Verwendung? Der Vorteil ist, dass alle internen Variablen über die Trigger zugänglich sind und der Code sehr einfach ist.

Siehe auf jsfiddle .

Anwendungsbeispiel

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

Plugin

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
vgl. dein Kommentar. Das einzige Problem, das ich hier sehe, ist wohl ein Missbrauch des Ereignissystems. Es ist untypisch, Ereignisse nur zum Aufrufen einer Funktion zu verwenden. es scheint wie ein Overkill und kann leicht gebrochen werden. Normalerweise würden Sie Ereignisse auf Publish-Subscribe-Weise verwenden, z. B. veröffentlicht eine Funktion, dass eine Bedingung "A" aufgetreten ist. Andere Entitäten, die an "A" interessiert sind, warten auf die Nachricht, dass "A" passiert ist, und tun dann etwas. Sie scheinen es stattdessen als Push-Befehl zu verwenden, nehmen jedoch an, dass es nur einen Listener gibt. Sie sollten darauf achten, dass Ihre Semantik nicht durch (andere) Hinzufügen von Listenern unterbrochen wird.
Tvanfosson

@tvanfosson Danke für deinen Kommentar. Ich verstehe, dass es keine übliche Technik ist und Probleme verursachen kann, wenn jemand versehentlich einen Ereignis-Listener hinzufügt, aber wenn er nach dem Plugin benannt ist, ist dies sehr unwahrscheinlich. Ich kenne keine leistungsbezogenen Probleme, aber der Code selbst scheint mir viel einfacher zu sein als bei den anderen Lösungen, aber mir fehlt möglicherweise etwas.
István Ujj-Mészáros

3

Hier möchte ich Schritte vorschlagen, um ein einfaches Plugin mit Argumenten zu erstellen.

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

Hier haben wir das aufgerufene paramsStandardobjekt hinzugefügt und die Standardwerte der Optionen mithilfe der extendFunktion festgelegt. Wenn wir also ein leeres Argument übergeben, werden stattdessen Standardwerte festgelegt, andernfalls wird es festgelegt.

Lesen Sie mehr: So erstellen Sie ein JQuery-Plugin


Hallo Gopal Joshi, bitte geben Sie die nächste Stufe der Erstellung eines JQuery-Plugins. Wir erwarten von Ihrer notwendigen Antwort.
Sakthi Karthik

Hallo @SakthiKarthik, natürlich werde ich bald ein neues Tutorial in meinem Blog veröffentlichen
Gopal Joshi

1
Hallo @SakthiKarthik, Sie können neuen Artikel auf der nächsten Ebene jquery Plugin hier sgeek.org/…
Gopal Joshi

2

Probier diese:

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

Hier ist meine Bare-Bones-Version davon. Ähnlich wie bei den zuvor geposteten würden Sie wie folgt anrufen:

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

-oder greifen Sie direkt auf die Instanz zu @ 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

Die folgende Plugin-Struktur nutzt die jQuery- data()-Methode eine öffentliche Schnittstelle zu internen Plugin-Methoden / -Einstellungen , um (während jQuery-Verkettbarkeit Erhaltung):

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

Jetzt können Sie interne Plugin-Methoden aufrufen, um mithilfe dieser Syntax auf Plugin-Daten oder das entsprechende Element zuzugreifen oder diese zu ändern:

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

Solange Sie das aktuelle Element (this) aus Ihrer Implementierung von myPublicPluginMethod()jQuery-chainability zurückgeben, bleibt Folgendes erhalten: Folgendes funktioniert:

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

Hier sind einige Beispiele (Einzelheiten finden Sie in dieser Geige ):

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

Dies kann tatsächlich dazu gebracht werden, auf "nette" Weise mit zu arbeiten defineProperty. Wobei "nett" bedeutet, dass Sie ()weder den Plugin-Namespace abrufen noch den Funktionsnamen als Zeichenfolge übergeben müssen.

Kompatibilitäts-Nit: Funktioniert defineProperty nicht in alten Browsern wie IE8 und niedriger. Vorsichtsmaßnahme: $.fn.color.blue.apply(foo, args) funktioniert nicht, müssen Sie verwenden 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


0

Gemäß dem jquery-Standard können Sie das Plugin wie folgt erstellen:

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

Wie rufe ich dieses Plugin auf?

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

Referenz: Link


0

Ich denke, das könnte dir helfen ...

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

Im obigen Beispiel hatte ich ein einfaches jquery- Highlight- Plugin erstellt. Ich hatte einen Artikel geteilt, in dem ich über das Erstellen eines eigenen jQuery-Plugins von Basic bis Advance gesprochen hatte. Ich denke, Sie sollten es überprüfen ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/


0

Im Folgenden finden Sie ein kleines Plug-In mit einer Warnmethode zum Debuggen. Behalten Sie diesen Code in der Datei 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

So mache ich das:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

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

-2

Sie haben im Grunde das Objekt jQuery.fn.messagePlugin um eine neue Methode erweitert. Welches ist nützlich, aber nicht in Ihrem Fall.

Sie müssen diese Technik anwenden

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

};

Aber Sie können erreichen, was Sie wollen. Ich meine, es gibt eine Möglichkeit, $ ("# mydiv") zu tun. MessagePlugin (). SaySomething ("hello"); Mein Freund, er hat angefangen, über Lugins zu schreiben, und wie man sie mit Ihrer Funktionskette erweitert, hier ist der Link zu seinem Blog

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.