4E e 4I Sia: utilizzo libreria Leaflet - Teoria delle classi

 Teoria delle classi



Leaflet ha letteralmente centinaia di plugin. Questi espandono le capacità di Leaflet: a volte in modo generico, a volte in modo molto specifico per il caso d'uso.

Parte del motivo per cui ci sono così tanti plugin è che Leaflet è facile da estendere. Questo tutorial tratterà i modi più comunemente usati per farlo.

Tieni presente che questo tutorial presuppone che tu abbia una buona conoscenza di:

Architettura del volantino

Diamo un'occhiata a un diagramma di classe UML semplificato per il volantino 1.0.0. Ci sono più di 60 classi JavaScript, quindi il diagramma è un po' grande. Fortunatamente possiamo creare un'immagine zoomabile con L.ImageOverlay:

Vedi questo esempio autonomo.

Da un punto di vista tecnico, Leaflet può essere ampliato in diversi modi:

  • Il più comune: creare una nuova sottoclasse di L.LayerL.HandlerL.Control, conL.Class.extend()
    • I livelli si spostano quando la mappa viene spostata/ingrandita
    • I gestori sono invisibili e interpretano gli eventi del browser
    • I controlli sono elementi di interfaccia fissi
  • Includere più funzionalità in una classe esistente conL.Class.include()
    • Aggiunta di nuovi metodi e opzioni
    • Modifica di alcuni metodi
    • Utilizzo addInitHookper eseguire codice costruttore aggiuntivo.
  • Modifica di parti di una classe esistente (sostituzione del funzionamento di un metodo di classe) con L.Class.include().

Questo tutorial copre alcune classi e metodi disponibili solo in Leaflet 1.0.0. Fai attenzione se stai sviluppando un plug-in per una versione precedente.

L.Class

JavaScript è un linguaggio un po' strano. Non è davvero un linguaggio orientato agli oggetti, ma piuttosto un linguaggio orientato ai prototipi . Ciò ha reso storicamente difficile JavaScript nell'usare l'ereditarietà delle classi nel classico significato OOP del termine.

Il volantino risolve questo problema avendo L.Class, che facilita l'ereditarietà della classe.

Anche se JavaScript moderno può utilizzare classi ES6, Leaflet non è progettato attorno a loro.

L.Class.extend()

Per creare una sottoclasse di qualsiasi cosa in Leaflet, usa il .extend()metodo. Questo accetta un parametro: un oggetto semplice con coppie chiave-valore, ogni chiave è il nome di una proprietà o metodo e ogni valore è il valore iniziale di una proprietà o l'implementazione di un metodo:

var MyDemoClass = L.Class.extend({

    // A property with initial value = 42
    myDemoProperty: 42,   

    // A method 
    myDemoMethod: function() { return this.myDemoProperty; }
    
});

var myDemoInstance = new MyDemoClass();

// This will output "42" to the development console
console.log( myDemoInstance.myDemoMethod() );   

Quando si nominano classi, metodi e proprietà, attenersi alle seguenti convenzioni:

  • I nomi di funzione, metodo, proprietà e fabbrica devono essere in lowerCamelCase.
  • I nomi delle classi dovrebbero essere in UpperCamelCase.
  • Le proprietà ei metodi privati ​​iniziano con un trattino basso ( _). Questo non li rende privati, consiglia solo agli sviluppatori di non usarli direttamente.

L.Class.include()

Se una classe è già definita, è possibile ridefinire proprietà/metodi esistenti o aggiungerne di nuovi utilizzando .include():

MyDemoClass.include({

    // Adding a new property to the class
    _myPrivateProperty: 78,
    
    // Redefining a method
    myDemoMethod: function() { return this._myPrivateProperty; }

});

var mySecondDemoInstance = new MyDemoClass();

// This will output "78"
console.log( mySecondDemoInstance.myDemoMethod() );

// However, properties and methods from before still exist
// This will output "42"
console.log( mySecondDemoInstance.myDemoProperty );

L.Class.initialize()

In OOP, le classi hanno un metodo di costruzione. In Leaflet's L.Class, il metodo del costruttore è sempre denominato initialize.

Se la tua classe ha alcuni specifici options, è una buona idea inizializzarli con L.setOptions()nel costruttore. Questa funzione di utilità unirà le opzioni fornite con le opzioni predefinite della classe.

var MyBoxClass = L.Class.extend({

    options: {
        width: 1,
        height: 1
    },

    initialize: function(name, options) {
        this.name = name;
        L.setOptions(this, options);
    }
    
});

var instance = new MyBoxClass('Red', {width: 10});

console.log(instance.name); // Outputs "Red"
console.log(instance.options.width); // Outputs "10"
console.log(instance.options.height); // Outputs "1", the default

Il volantino gestisce la optionsproprietà in modo speciale: le opzioni disponibili per una classe genitore verranno ereditate da una classe figli:.

var MyCubeClass = MyBoxClass.extend({
    options: {
        depth: 1
    }
});

var instance = new MyCubeClass('Blue');

console.log(instance.options.width); // Outputs "1", parent class default
console.log(instance.options.height); // Outputs "1", parent class default
console.log(instance.options.depth); // Outputs "1"

È abbastanza comune che le classi figlie eseguano il costruttore del genitore e quindi il proprio costruttore. In Leaflet questo si ottiene usando L.Class.addInitHook()Questo metodo può essere utilizzato per "agganciare" le funzioni di inizializzazione che vengono eseguite subito dopo la classe' initialize(), ad esempio:

MyBoxClass.addInitHook(function(){
    this._area = this.options.width * this.options.length;
});

Che verrà eseguito dopo initialize()viene chiamato (che chiama setOptions()). Ciò significa che this.optionsesiste ed è valido quando viene eseguito l'hook init.

addInitHookha una sintassi alternativa, che usa i nomi dei metodi e può riempire gli argomenti dei metodi in:

MyCubeClass.include({
    _calculateVolume: function(arg1, arg2) {
        this._volume = this.options.width * this.options.length * this.options.depth;
    }
});

MyCubeClass.addInitHook('_calculateVolume', argValue1, argValue2);

Metodi della classe madre

La chiamata a un metodo di una classe genitore si ottiene accedendo al prototipo della classe genitore e usando Function.call(…)Questo può essere visto, ad esempio, nel codice per L.FeatureGroup:

L.FeatureGroup = L.LayerGroup.extend({

    addLayer: function (layer) {
        …
        L.LayerGroup.prototype.addLayer.call(this, layer);
    },
    
    removeLayer: function (layer) {
        …
        L.LayerGroup.prototype.removeLayer.call(this, layer);
    },

    …
});

La chiamata al costruttore del genitore viene eseguita in modo simile, ma utilizzando ParentClass.prototype.initialize.call(this, …)invece.

Fabbriche

La maggior parte delle classi di volantini hanno una funzione di fabbrica corrispondente . Una funzione factory ha lo stesso nome della classe, ma lowerCamelCaseinvece di UpperCamelCase:

function myBoxClass(name, options) {
    return new MyBoxClass(name, options);
}

Convenzioni di denominazione

Quando si assegnano nomi alle classi per i plug-in Leaflet, attenersi alle seguenti convenzioni di denominazione:

  • Non esporre mai variabili globali nel tuo plugin.
  • Se hai una nuova classe, inseriscila direttamente nello spazio dei Lnomi ( L.MyPlugin).
  • Se erediti una delle classi esistenti, rendila una sottoproprietà ( L.TileLayer.Banana).


Commenti

Post popolari in questo blog

Simulazioni di reti (con Cisco Packet Tracer)

Esercizi sulla rappresentazione della virgola mobile IEEE 754 (Floating Point)