6

Per motivi di esercizio sto creando un plugin jQuery, un semplice dispositivo di scorrimento delle immagini. Io uso un modello da Boilerplate - jQuery Plugins.jQuery Plugin Sviluppo come mantenere private variabili e metodi

Durante il processo di inizializzazione tutto funziona come previsto, ogni istanza ottiene i valori corretti (larghezze e altezze, anche binding di eventi) necessari per l'installazione.

Il problema inizia quando provo a passare una larghezza di diapositiva calcolata a una funzione che fa l'animazione (clic sul pulsante successivo). Ogni valore che ho provato a salvare è stato sovrascritto dall'ultima istanza - ok, questo è ciò che l'ereditarietà del prototipo fa, come ho imparato.

Ho cercato su Google e ho trovato (non solo) questa soluzione su stockoverflow: global or local variables in a jquery-plugin. La risposta accettata suggerisce di memorizzare valori che devono essere privati ​​nel markup HTML, l'attributo data-whatever.

Questo funziona molto bene, ma non è molto bello.

La seconda risposta sembra essere più elegante, mantenendo le variabili private reali nel perimetro di ogni istanza:

(function($) { 

$.pluginName = function(element, options) { 
.... 
var plugin = this; 
.... 
     // a public method 
    plugin.foo_public_method = function() { 
      .... 
    } 

    // private methods 
    var foo_private_method = function() { 
      .... 
    } 
    plugin.init(); 

} .... 

sembrava abbastanza semplice - ma non sono in grado di implementare questa soluzione!

Quindi la mia domanda è: come implementare una variabile privata nel seguente modello di plug-in? (E come lo chiamo correttamente da dentro Plugin.prototype ...)

Ho creato un Fiddle con il mio plugin. Un estratto del codice:

(function ($, window, document, undefined) { 

var pluginName = "easyCarousel"; 

// default configuration object 
defaults = { 
     ... default values here, css etc 
    } 
}; 

// The actual plugin constructor 
function Plugin(element, options) { 

    this.element = element; 
    this.options = $.extend({}, defaults, options); 
    this._defaults = defaults; 
    this._name = pluginName; 
    this.init(); 
} 

Plugin.prototype = { 

    init: function() { 

     var options = this.options; 
     this.options.stage = $(this.element); 
     .... calling/starting views and controllers 

    }, 

    buildCollectionView: function (options, Helper) { 
     .... setting markup, applying css, calulating dimensions 
    }, 

    buildStageView: function (options, Helper) { 

     .... setting markup, applying css 
     .... storing calculated slide width in data Attribute 

     stage.attr({ 
      'data-slidewidth': width, 
      'data-stagewidth': setWidth 
     }); 
    }, 

    buildTheatreView: function (options, Helper) { 

     .... setting markup, applying css 

    }, 

    buildNavigationView: function (options) { 

     .... setting markup 

    }, 


    navigationController: 

    function (options, slideForward, slideBackward) { 

     .... event binding 

     pubSub.on("navigation:arrownext:click", function (e) { 
      slideForward(options, e); 
     }); 

     $('.carousel__arrownext', options.theatre) 
     .bind('click', function() { 
      pubSub.trigger("navigation:arrownext:click", this); 
     }); 
    }, 

    slideForwardAnimation: function (options, e) { 

     .... reading stored width value from data Attribute 

     $element.animate({ 
      "left": "-=" + slideWidth 
     }) 
    }, 


    setDimensionsHelper: function (options) { 

     .... calculating an returning dimensions of the slider 
    }, 

    eventBusHelper: function (options) { 
     // integrating third party eventbus 
    } 
}; 

$.fn[pluginName] = function (options) { 

    return this.each(function() { 
     if (!$.data(this, "plugin_" + pluginName)) { 
      $.data(this, "plugin_" + pluginName, 
      new Plugin(this, options)); 
     } 
    });  
}})(jQuery, window, document); 

Spero che il mio esempio di codice non sia complicato/lungo da visualizzare.

Come potete vedere, sono abbastanza nuovo per i modelli Javascript avanzati - e in questo momento sono davvero bloccato. Passo già molte ore in questo problema. Quindi ogni tentativo di aiutare è molto apprezzato. Ovviamente ogni recensione sul codice.

Grazie in anticipo :)

+0

"* Ogni valore, che ho cercato di salvare è stato sovrascritto dal ultima istanza - ok, questo è ciò che il prototipo l'ereditarietà fa * "- um, no. – Bergi

+0

Non capisco perché vorreste variabili "private" per il vostro plugin? Inoltre, se sono locali al costruttore dell'istanza, significa che non puoi accedervi dal prototipo. – Bergi

+0

"..perché vorresti" privato ..?"Semplicemente per un utilizzo successivo, calcolo la larghezza di una diapositiva durante la costruzione della giostra. Più avanti ho bisogno di questa larghezza quando si fa clic sul pulsante successivo (scorre la giostra di questa larghezza x ulteriormente). È più facile leggere questo valore da una variabile ricalcolo ripetutamente (spero che il termine privato sia corretto in questo contesto) Comincio a chiedermi se ho frainteso l'intero concetto ei miei calcoli non dovrebbero entrare nel prototipo.Come vorresti ottenere questo risultato? Grazie per il risposta! – smaug333

risposta

3

Tutto quello che dovete fare è definire le variabili all'interno del vostro prototipo (direttamente o da un metodo nel prototipo) piuttosto che farlo nel costruttore. Le variabili definite nel costruttore saranno condivise tra tutte le istanze del tuo plugin, mentre le variabili definite nel prototipo saranno peristanza.

Inoltre, non esiste una parola chiave "var" davanti alla definizione "predefinite", quindi in effetti stai creando una variabile globale denominata "valori predefiniti" anziché una che ha lo scopo solo della chiusura.

Questo è quello che mi consiglia:

// default configuration object 
var defaults = { 
     ... default values here, css etc 
    } 
}; 

// The actual plugin constructor 
function Plugin(element, options) { 
    this._defaults = defaults; 
    this._name = pluginName; 
    this.init(element, options); 
} 

Plugin.prototype = { 

    init: function (element, options) { 
     this.element = element; 
     this.options = $.extend({}, this._defaults, options); 
     this.options.stage = $(this.element); 
     .... calling/starting views and controllers 

    }, 

o meglio ancora:

// The actual plugin constructor 
function Plugin(element, options) { 
    this.init(element, options); 
} 

Plugin.prototype = { 

    _name: 'put your name here', 

    _defaults: { 
     // just define them here, no need for an outside variable 
    }, 

    init: function (element, options) { 
     this.element = element; 
     this.options = $.extend({}, this._defaults, options); 

     // why are you saving stage as an option? That doesn't make sense. 
     this.options.stage = $(this.element); 
     // Makes more sense to just do this ($el is a more standard name for this) 
     this.$el = $(this.element); 
     // .... calling/starting views and controllers 

    }, 
+0

Grazie, molto elegante e funziona come un fascino – smaug333

+0

I mancava "var" nella mia dichiarazione di opzioni. Sigh ... – Bobort

Problemi correlati