Yöntemlerle bir jQuery eklentisi nasıl oluşturulur?


191

Ek işlevler / yöntemleri çağıran nesneye sağlayacak bir jQuery eklentisi yazmaya çalışıyorum. Çevrimiçi okuduğum tüm eğiticiler (son 2 saattir göz atıyorum) en fazla nasıl seçenek ekleneceğini, ancak ek işlevleri içermiyor.

İşte yapmak istediğim şey:

// div'in söz konusu div için eklentiyi çağırarak ileti taşıyıcısı olarak biçimlendirmesi

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

veya bu çizgiler boyunca bir şey. İşte bunun için kaynar: Eklentiyi çağırıyorum, sonra bu eklentiyle ilişkili bir işlevi çağırıyorum. Bunu yapmanın bir yolunu bulamıyorum ve daha önce birçok eklentinin bunu yaptığını gördüm.

İşte eklenti için şimdiye kadar ne var:

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

Böyle bir şeyi nasıl başarabilirim?

Teşekkür ederim!


18 Kasım 2013 Güncellemesi: Hari'nin aşağıdaki yorum ve upvotes cevabının doğru cevabını değiştirdim.

Yanıtlar:


310

JQuery Eklenti Yazma sayfasına ( http://docs.jquery.com/Plugins/Authoring ) göre, jQuery ve jQuery.fn ad alanlarını çamurlamamak en iyisidir. Bu yöntemi önerirler:

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

Temel olarak işlevlerinizi bir dizide saklarsınız (kaydırma işlevine dahil edilir) ve geçirilen parametrenin bir dize olup olmadığını kontrol edersiniz, parametre bir nesne (veya null) ise varsayılan bir yönteme ("init") geri döner.

Sonra böyle yöntemleri çağırabilirsiniz ...

$('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 "arguments" değişkeni, geçirilen tüm argümanların bir dizisidir, bu nedenle işlev parametrelerinin keyfi uzunluklarıyla çalışır.


2
Kullandığım yöntem bu. Yöntemleri $ .fn.tooltip ('yöntemadı', params) aracılığıyla statik olarak da çağırabilirsiniz;
Komisyon36

1
Çok kullanışlı mimari. Ayrıca init yöntemini çağırmadan önce bu satırı ekledim: this.data('tooltip', $.extend(true, {}, $.fn.tooltip.defaults, methodOrOptions));şimdi başlatmadan sonra istediğim zaman seçeneklere erişebiliyorum.
ivkremer

16
Benim gibi "argüman değişkeni nereden geldi?" Diyen benim için - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - JS'yi sonsuza kadar kullanıyorum ve bunu hiç bilmiyordum. Her gün yeni bir şey öğreniyorsun!
streetlogics

2
@DiH, bu konuda seninleyim. Bu yaklaşım harika görünüyor, ancak küresel ayarlarınıza başka bir yerden erişmenize izin vermiyor init.
Stephen Collins

4
Bu teknikle ilgili büyük bir sorun var! Seçicideki yaptığınız gibi her öğe için yeni bir örnek oluşturmaz, bunun yerine seçicinin kendisine eklenmiş tek bir örnek oluşturur. Çözüm için cevabımı görüntüle .
Kevin Jurkowski

56

İşte ek yöntemlerle eklentiler oluşturmak için kullandığım desen. Bunu şöyle kullanırsınız:

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

veya doğrudan bir yöntemi çağırmak için,

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

Misal:

;(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 ile aynı desen, tüm sihirli dizeleri sevmiyorum ama başka bir yolu var!
redsquare

8
Bu, standart bir şey yapmanın yolu gibi görünüyor - zincirleme fonksiyonları gibi bundan daha basit bir şey var mı? teşekkür ederim!
Yuval Karmi

2
@yuval - tipik olarak jQuery eklentileri eklentinin kendisini değil, jQuery veya bir değer döndürür. Bu nedenle, eklentiyi çağırmak istediğinizde yöntemin adı eklentiye bağımsız değişken olarak iletilir. İstediğiniz sayıda bağımsız değişkeni iletebilirsiniz, ancak işlevleri ve bağımsız değişken ayrıştırmayı ayarlamanız gerekir. Muhtemelen gösterdiğiniz gibi anonim bir nesneye yerleştirmek en iyisidir.
tvanfosson

1
;İlk satırınızdaki anlamı nedir ? lütfen bana açıkla :)
GusDeCooL

4
@GusDeCooL, işlev tanımımızın başka birinin kötü biçimlendirilmiş Javascript'i için bir argüman olarak yorumlanmaması için yeni bir ifade başlattığımızdan emin olur (yani, ilk paren bir işlev çağırma operatörü olarak alınmaz). Bkz. Stackoverflow.com/questions/7365172/…
tvanfosson

35

Bu yaklaşım ne olacak:

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

Seçilen nesneler messagePlugin kapatılmasında saklanır ve bu işlev eklentiyle ilişkili işlevleri içeren bir nesne döndürür, her işlevde seçili olan nesnelere istediğiniz eylemleri gerçekleştirebilirsiniz.

Buradaki kodu test edebilir ve oynayabilirsiniz .

Düzenleme: jQuery zincirlenebilirliğinin gücünü korumak için güncellenmiş kod.


1
bunun neye benzeyeceğini anlamakta biraz zorlanıyorum. Bu ilk çalıştırıldığında yürütülmesi gereken bir kod var varsayarsak, ben ilk olarak benim kodu - böyle bir şey başlatmak gerekir: $ ('p'). MessagePlugin (); daha sonra kodda ben bu $ ('p') gibi saySomething işlevini çağırmak istiyorum. messagePlugin (). saySomething ('bir şey'); eklentiyi yeniden başlatmaz ve sonra işlevi çağırmaz mı? kasa ve seçeneklerle bu nasıl olurdu? çok teşekkür ederim. -yuval
Yuval Karmi

1
Yine de jQuery'nin zincirlenebilirlik paradigmasını kırar.
tvanfosson

belki de bu en iyi cevap olmalı
Dragouf

3
MessagePlugin () öğesini her aradığınızda, bu iki işlevle yeni bir nesne oluşturur, değil mi?
w00t

4
Bu yaklaşımla ilgili temel sorun, $('p').messagePlugin()döndürdüğü iki işlevden birini çağırmazsanız, aşağıdaki zincirlenebilirliği koruyamamasıdır .
Joshua Bambrick

18

Şu anda seçili yanıtla ilgili sorun, aslında seçicideki her öğe için yaptığınız gibi özel bir eklentinin yeni bir örneğini oluşturmamanız ... aslında yalnızca tek bir örnek oluşturuyorsunuz ve kapsam olarak seçicinin kendisi.

Bu kemanı görüntüle derin bir açıklama için .

Bunun yerine, jQuery.each kullanarak seçiciyi döngüye almanız gerekir ve her öğe için özel eklentinin yeni bir örneğini başlatmanız gerekir.

Bunu nasıl yapacağınız aşağıda açıklanmıştır:

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

Ve çalışan bir keman .

İlk kemanda, tüm div'lerin her zaman tam olarak aynı sayıda piksele nasıl sağlandığını göreceksiniz. Çünkü sadece bir , seçicideki tüm öğeler için seçenek nesnesinin bulunmasıdır.

Yukarıda yazılı tekniği kullanarak, ikinci kemanda, her divin hizalanmadığını ve rastgele hareket ettiğini fark edeceksiniz (randomizatör her zaman 89 satırında 1 olarak ayarlandığından ilk div hariç). Bunun nedeni, şimdi seçicideki her öğe için yeni bir özel eklenti örneğini düzgün bir şekilde somutlaştırmamızdır. Her öğenin kendi seçenekler nesnesi vardır ve seçiciye değil, özel eklentinin kendisinde saklanır.

Bu, yeni jQuery seçicilerinden DOM'daki belirli bir öğede başlatılan özel eklentinin yöntemlerine erişebileceğiniz ve ilk kemanda olacağınız gibi önbelleğe almanız gerekmeyeceği anlamına gelir.

Örneğin, bu, ikinci kemandaki tekniği kullanarak tüm seçenek nesnelerinin bir dizisini döndürür. İlkinde tanımsız dönecekti.

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

İlk kemandaki seçenekler nesnesine şu şekilde erişmeniz gerekir ve bunların bir dizisini değil, yalnızca tek bir nesneyi döndürürsünüz:

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

Seçili cevaptan değil, yukarıdaki tekniği kullanmanızı öneririm.


Teşekkürler, bu bana çok yardımcı oldu, özellikle .data () yöntemini bana tanıttı. Çok kullanışlı. FWIW, anonim yöntemler kullanarak bazı kodlarınızı basitleştirebilirsiniz.
dalemac

jQuery chainability bu yöntemi kullanarak çalışmıyor ... $('.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 Fabrikasının tanıtımıyla bunu çok daha kolay hale getirdi .

Misal:

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

});

Başlatma:

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

Yöntem çağırma:

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

( JQuery UI kitaplığı bu şekilde oluşturulur.)


@ daniel.sedlacek a) "çok kötü mimari" - bu jQuery standart widget mimarisi b) "derleme zamanında bütünlük kontrolü" - JavaScript dinamik bir dildir c) "TypeScript" - ne?
Yarin

a) bu argümanum reklam popülasyonu, b) her daha iyi JS IDE'nin kod tamamlama veya lintingi vardır, c) google it
daniel.sedlacek

Bu tam bir yanılsama, Bay Sedlacek.
mystrdat

Dokümanlar başına: Bu sistem Widget Fabrikası olarak adlandırılır ve jQuery UI 1.8'in bir parçası olarak jQuery.widget olarak kullanılır; ancak, jQuery kullanıcı arayüzünden bağımsız olarak kullanılabilir. $ .Widget jQuery kullanıcı arayüzü olmadan nasıl kullanılır ?
Airn5475

13

Daha basit bir yaklaşım, iç içe geçmiş işlevleri kullanmaktır. Sonra onları nesne yönelimli bir şekilde zincirleyebilirsiniz. Misal:

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

Ve işte şöyle diyeceksiniz:

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

Yine de dikkatli olun. Yuvalanmış bir işlevi oluşturulana kadar çağıramazsınız. Yani bunu yapamazsın:

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

DoEvenMore işlevi, DoEomMore işlevini oluşturmak için gereken DoSomething işlevi henüz çalıştırılmadığından bile mevcut değildir. Çoğu jQuery eklentisi için, burada gösterdiğim gibi iki değil, yalnızca bir düzey iç içe işlevlere sahip olacaksınız.
Üst işlevdeki diğer kodlar yürütülmeden önce bu işlevleri üst işlevlerinin başında tanımladığınız iç içe işlevler oluşturduğunuzdan emin olun.

Son olarak, "this" üyesinin "_this" adlı bir değişkende saklandığını unutmayın. Yuvalanmış işlevler için, çağıran istemcideki örneğe başvurmanız gerekirse "_this" ifadesini döndürmelisiniz. JQuery örneğine değil, işleve bir başvuru döndüreceğinden iç içe işlevde yalnızca "this" i döndüremezsiniz. Bir jQuery başvurusunun döndürülmesi, dönüşte gerçek jQuery yöntemlerini zincirlemenizi sağlar.


2
Bu harika - neden sadece jQuery neden .plugin ('method') deseninde olduğu gibi yöntemleri adıyla çağırmak gibi görünüyor?
w00t

6
Bu çalışmıyor. Eklentiyi iki farklı kapsayıcıya çağırırsanız, iç değişkenler geçersiz kılınır (yani _this)
mbrochh

Başarısız: pluginContainer.MyPlugin.DoEvenMore () öğesine izin vermez. DoSomething ();
Paul Swetz

9

Bunu jQuery Plugin Boilerplate'den aldım

Ayrıca jQuery Eklenti Boilerplate, açıklamak

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

Kişisel yöntem breaks jQuery zincirleme: $('.first-input').data('pluginName').publicMethod('new value').css('color', red);döner Cannot read property 'css' of undefined jsfiddle.net/h8v1k2pL/1
Alex G

@AlexG bu örneği eklediğinizde return $element, bu örnekte plugin.foo_public_method = function() {/* Your Code */ return $element;}bana yardımcı olduğunuz için teşekkürler @Salim olarak değiştirirsiniz ... github.com/AndreaLombardo/BootSideMenu/pull/34
CrandellWS

6

Çok geç ama belki bir gün birine yardım edebilir.

Bazı yöntemlerle bir jQuery eklentisi oluşturmak gibi bir durumdaydım ve bazı makaleleri ve bazı lastikleri okuduktan sonra bir jQuery eklenti kazan plakası ( https://github.com/acanimal/jQuery-Plugin-Boilerplate ) oluşturdum.

Buna ek olarak, etiketleri yönetmek için bir eklenti geliştirdim ( https://github.com/acanimal/tagger.js ) ve adım adım bir jQuery eklentisinin ( http: // acuriousanimal) oluşturulmasını açıklayan iki blog yazısı yazdım. com.tr / blog / 2013/01/15 / things-i-learned-create-a-jquery-eklenti-bölüm-i / ).


muhtemelen bir acemi olarak jQuery eklentileri oluşturma hakkında henüz karşılaştığım en iyi yazı - teşekkürler;)
Dex Dave

5

Yapabilirsin:

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

Bu şekilde, plugins nesneniz öğenizde veri değeri olarak depolanır.

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

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

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

3

Tetikleyicileri kullanmaya ne dersiniz? Bunları kullanmanın herhangi bir dezavantajı bilen var mı? Avantajı, tüm dahili değişkenlere tetikleyiciler aracılığıyla erişilebilir olması ve kodun çok basit olmasıdır.

Bkz. Jsfiddle .

Örnek kullanım

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

Eklenti

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
bakınız senin yorumun. Burada gördüğüm tek sorun muhtemelen olay sisteminin yanlış kullanılmasıdır. Olayları yalnızca bir işlevi çağırmak için kullanmak atipiktir; aşırıya kaçmış gibi görünüyor ve kolayca kırılabilir. Normalde, etkinlikleri yayınlama-abone olma biçiminde kullanırsınız, örneğin bir işlev "A" koşulunun oluştuğunu yayınlar. "A" ile ilgilenen diğer varlıklar, "A" nın olduğunu bildiren mesajı dinledikten sonra bir şeyler yapın. Bunun yerine push "command" olarak kullanılıyor gibi görünüyor, ancak yalnızca bir dinleyici olduğu varsayılarak. Anlambilimlerinizin dinleyici ekleyerek (diğerleri) bozulmamasına dikkat etmek istersiniz.
tvanfosson

@tvanfosson Yorumunuz için teşekkürler. Ortak bir teknik olmadığını ve yanlışlıkla bir olay dinleyicisi eklerse sorunlara neden olabileceğini anlıyorum, ancak eklentiden sonra adlandırılırsa, çok olası değildir. Performansla ilgili herhangi bir sorun hakkında bilmiyorum, ancak kodun kendisi benim için diğer çözümlerden çok daha basit görünüyor, ancak bir şey eksik olabilir.
István Ujj-Mészáros

3

Burada argümanlarla basit bir eklenti oluşturmak için adımlar önermek istiyorum.

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

Burada, fonksiyonunu paramskullanarak varsayılan nesne ekledik ve seçeneklerin varsayılan değerlerini ayarladık extend. Bu nedenle, boş argümanı iletirsek, varsayılan değerleri ayarlar, aksi takdirde ayarlanır.

Daha fazla bilgi için: JQuery eklentisi nasıl oluşturulur?


Merhaba Gopal Joshi, Lütfen bir sonraki seviye jquery eklentisi oluşturma verin. biz sizin gerekli cevap bekliyoruz.
Sakthi Karthik

Merhaba @SakthiKarthik, Mahkemeden yakında yeni eğiticiyi blogumda yayınlayacağım
Gopal Joshi

1
Merhaba @SakthiKarthik, Bir sonraki seviyedeki jquery eklentisi ile ilgili yeni makalelere buradan ulaşabilirsiniz sgeek.org/…
Gopal Joshi

2

Bunu dene:

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

İşte bunun çıplak kemiklerim versiyonu. Daha önce yayınlananlara benzer şekilde şöyle diyebilirsiniz:

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

-veya örneğe doğrudan erişme @ 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

Aşağıdaki eklenti yapısı , dahili eklenti yöntemlerine / ayarlarına (jQuery-chainability korunurken) genel bir arabirim sağlamak için jQuery- data()yöntemini kullanır :

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

Artık bu sözdizimini kullanarak eklenti verilerine veya ilgili öğeye erişmek veya değiştirmek için dahili eklenti yöntemlerini çağırabilirsiniz:

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

myPublicPluginMethod()JQuery-chainability uygulamanızın içinden geçerli öğeyi (bu) döndürdüğünüz sürece korunur - bu nedenle aşağıdaki işler:

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

İşte bazı örnekler (ayrıntılar için bu kemanı kontrol edin ):

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

Bu aslında kullanarak "güzel" bir şekilde çalışmak için yapılabilir defineProperty. Burada "nice", ()eklenti ad alanını almak için kullanmak zorunda kalmadan veya işlev adını dizeyle geçirmek zorunda kalmadan anlamına gelir .

Uyumluluk nit: defineProperty IE8 ve önceki gibi eski tarayıcılarda çalışmaz. Dikkat: $.fn.color.blue.apply(foo, args) işe yaramaz, kullanmanız gerekir 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 bağlantısı


0

Jquery standardına göre aşağıdaki gibi eklenti oluşturabilirsiniz:

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

Bu eklenti nasıl adlandırılır?

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

Referans: bağlantı


0

Sanırım bu sana yardımcı olabilir ...

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

Yukarıdaki örnekte, basit bir jquery vurgu eklentisi oluşturmuştum.Konudan Advance'e kendi jQuery Eklentinizi Oluşturma hakkında tartıştığım bir makale paylaşmıştım . Bence kontrol etmelisin ... http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/


0

Aşağıda, hata ayıklama amacıyla uyarı yöntemine sahip küçük bir eklenti bulunmaktadır. Bu kodu jquery.debug.js dosyasında saklayın: 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

İşte nasıl yaparım:

(function ( $ ) {

$.fn.gridview = function( options ) {

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


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

    ........

};

}( jQuery ));


var htmlFactory = function(){

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

-2

Yaptığınız temelde jQuery.fn.messagePlugin nesnesini genişletmek yeni yöntemle . Bu yararlı ama sizin durumunuzda değil.

Yapmanız gereken bu tekniği kullanmak

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

};

Ama istediğinizi başarabilirsiniz $ ("# mydiv") yapmak için bir yol var demek istiyorum. MessagePlugin (). SaySomething ("merhaba"); Arkadaşım o lugins hakkında yazmaya başladı ve onları burada işlevsellik zinciri ile genişletmek için onun blog bağlantısı

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.