In questo articolo, esamineremo il processo di utilizzo di JavaScript, da una prospettiva basata su MVC, per manipolare il DOM. Più specificamente, progetteremo i nostri oggetti JavaScript, le loro proprietà e metodi e le loro istanze parallelamente al comportamento previsto delle nostre visualizzazioni (ciò che l'utente vede).
In qualsiasi momento dello sviluppo di una pagina Web, stiamo utilizzando un linguaggio che promuove naturalmente lo sviluppo basato su classi o lo sviluppo basato su oggetti. In linguaggi fortemente tipizzati come Java e C #, di solito scriviamo le nostre viste in classi, dando loro stato, ambito e contesto. Quando lavoriamo con linguaggi come PHP o motori di visualizzazione più recenti, come Razor per ASP.NET, le nostre viste possono semplicemente essere marcate (HTML / CSS) mescolate con il template. Tuttavia, questo non significa che dobbiamo cambiare la nostra percezione di come la vista si comporta come una propria entità statica.
All'interno di Views, stiamo principalmente lavorando con HTML, che consiste di elementi nidificati; questi elementi hanno attributi che descrivono quale sia il loro scopo semantico o come appaiono quando sono resi. Questi elementi hanno quindi elementi figli o genitori che ereditano / forniscono comportamenti a cascata (tramite CSS) e di blocco / in linea. Questi elementi possono essere naturalmente visualizzati da una prospettiva OOP (Object-Oriented Programming). Si consideri, ad esempio, il seguente markup:
div.container border: 1px solid # 333; imbottitura: 5px; colore rosso;
Riguardo la nostra compagnia
Come puoi vedere sopra, l'intestazione ha ereditato la sua proprietà color font dal suo contenitore genitore attraverso il comportamento CSS della cascata. Questo comportamento è abbastanza simile al concetto di ereditarietà in OOP. Possiamo anche vedere che l'intestazione è un figlio del contenitore, ereditando determinate proprietà, in base al comportamento dell'elemento. Quando vediamo i nostri elementi da questa prospettiva, abbiamo una definizione migliore di ciò che intendiamo fare con i nostri elementi di visualizzazione e possiamo incapsulare meglio stili e funzionalità.
All'interno di una vista, avremo markup. Tuttavia, questo markup può avere viste parziali nidificate come barre laterali, un'intestazione, un piè di pagina, una guida a destra (o sinistra) e una o più sezioni di contenuto. Tutte queste viste parziali dovrebbero essere viste come una propria entità, in grado di avere il proprio stato, contesto e ambito.
"Quando si concepiscono le viste e le viste parziali come oggetti, è molto più semplice scrivere il codice lato client."
Molti sviluppatori tendono a scrivere JavaScript da un punto di vista procedurale o funzionale, e spesso trascurano di considerare le tendenze naturali offerte negli approcci di sviluppo basati sulla vista e nell'istanza parallela (creando una nuova istanza della vista quando creiamo una nuova istanza di un JavaScript oggetto corrispondente a quella vista) quando si lavora in MVC Frameworks. Capita spesso di incappare in file JavaScript che sono solo un metodo dopo l'altro. Sebbene questo comportamento funzioni e sia comune, non è molto efficiente per la manutenzione del codice, il debug o l'estensione del codice corrente o futuro quando si lavora ampiamente con le viste.
Per allontanarti da questa abitudine e iniziare a scrivere un codice comportamentale migliore, quando inizi a disporre gli script e gli stili della tua vista, segui queste regole generali:
Si consideri il seguente diagramma:
Generalmente creo script e stili specifici per le viste e poi afferro ciò che mi serve dai fogli di stile e dalle librerie di script principali che ho creato che sarebbero stati usati su molte viste. Questo riduce anche la quantità di codice che viene utilizzato.
In questo articolo, definiremo la struttura per la pagina Chi siamo su un sito basato su MVC. Per iniziare, creeremo la struttura come mostrato sopra nel diagramma precedente. Da lì, creeremo un oggetto About e inizieremo ad aggiungere metodi al prototipo. Innanzitutto, considera il seguente layout visivo:
Questo è un layout molto logico e comunemente usato per una pagina web. Possiamo segmentare la nostra pagina in oggetti visivi separati. Per ognuna di queste viste, possiamo creare un oggetto logico che corrisponderà ad esso. In genere ometto le informazioni ripetitive nel nome file o nel nome della classe che viene utilizzato da MVC per determinare l'URI dalla rotta e invece si attaccano a qualcosa che è facile da mantenere coerente.
Per le visualizzazioni di pagina, generalmente chiamo i miei oggetti JavaScript con il nome della vista. Ecco un esempio del mio oggetto AboutView:
// Visualizza nome file: AboutView.cs (.NET MVC 1.0), About.cshtml (.NET MVC 3.0) o AboutView.php (PHP) var About = function (pageTitle) this.pageTitle = pageTitle; // associa gli eventi non appena l'oggetto viene istanziato this.bindEvents (); ;
Nell'esempio precedente, abbiamo creato un oggetto JavaScript nel formato della funzione, dandogli la capacità di fungere da costruttore di oggetti per tutti i metodi chiamati per la vista about. Scegliendo questo formato, possiamo creare un'istanza di una nuova istanza di Questo, proprio come facciamo con la nostra vista lato server (dicendo nuovo AboutView ();
). Da qui, possiamo assegnare proprietà e metodi a questo oggetto. Per assegnare metodi a questo oggetto, avremo bisogno di accedere al prototipo dell'oggetto.
Gli sviluppatori sono spesso ostacolati dall'elusività (e dall'ambiguità) del prototipo Object di JavaScript.
Gli sviluppatori sono spesso ostacolati dall'elusività (e dall'ambiguità) del prototipo Object di JavaScript. Per molti, può essere fonte di confusione usare e comprendere e aggiunge un'altra dimensione alla codifica. Poiché JavaScript diventa più guidato dagli eventi con i concetti HTML5, AJAX e Web 2.0, JavaScript tende a propendere naturalmente allo sviluppo procedurale facile da sviluppare ma difficile da mantenere, scalare e replicare.
Pensa alla parola Prototipo come un termine improprio per ora. Quando penso Prototipo, Penso a una "bozza di massima" o una base per l'ereditarietà, ma non è esattamente il caso.
"In realtà, la prospettiva migliore per Prototype sarebbe il puntatore dell'oggetto in memoria."
Quando creiamo un oggetto, istanziamo una nuova istanza di esso. Quando lo facciamo, creiamo un posto in memoria che l'oggetto possa essere referenziato (ricorda, gli oggetti in JavaScript lo sono tipi di riferimento, tipi non primitivi; creando un'altra variabile uguale a quell'oggetto e quindi cambiando i suoi valori in realtà cambierà l'oggetto originale nel puntatore). Quando creiamo un oggetto, istanziamo una nuova istanza di esso, quindi modifichiamo il suo "Puntatore" o Prototipo, aggiungiamo campi e metodi a quell'oggetto direttamente in memoria (ovviamente vogliamo aggiungere tutte queste cose prima dell'istanziazione).
Ecco un esempio di creazione di metodi su Di
prototipo dell'oggetto:
var About = function (pageTitle) this.pageTitle = pageTitle; // associa gli eventi non appena l'oggetto viene istanziato this.bindEvents (); ; var About.prototype.bindEvents = function () // Contesto corrente: 'this' è l'oggetto About // Posiziona tutte le associazioni di eventi in un unico posto e richiamale // nei propri metodi, se necessario. $ ('ul.menu'). on ('click', 'li.search', $ .proxy (this.toggleSearch, this)); ; var About.prototype.toggleSearch = function (e) // Attiva / disattiva la funzione di ricerca nella pagina;
Come puoi vedere sopra, abbiamo contenuto le proprietà dell'oggetto About all'interno del costruttore, abbiamo creato un singolo punto di riferimento per gli eventi di binding (in questo caso stiamo usando jQuery per creare i binding di evento, ma puoi usare qualsiasi framework o JavaScript stesso) e hanno posizionato il metodo toggleSearch sul prototipo dell'oggetto About per contenere quel metodo su quell'oggetto. Abbiamo anche chiamato il bindEvents ()
metodo nell'oggetto in modo che venga chiamato in istanza.
Ora, considera il seguente codice per la vista parziale della sidebar:
var pSidebar = function (pageTitle) this.pageTitle = pageTitle; // chiama il metodo bindEvents sulla creazione di istanze dell'oggetto pSidebar. // questo collegherà gli eventi all'oggetto this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // contesto corrente: 'this' è l'oggetto Sidebar $ ('ul.menu'). on ('click', 'li.has-submenu', $ .proxy ( this.toggleSubMenu, this)); $ ('input # search'). on ('click', $ .proxy (this.openSearch, this)); ; var pSidebar.prototype.toggleSubMenu = function (e) // attiva / disattiva i sottomenu // contesto corrente: 'this' is the pSidebar obj;
NOTA: Ho chiamato l'oggetto pSidebar
perché questo è un vista parziale, non una visione completa. Questa è la mia preferenza per distinguere tra i due, ma rende le cose più chiare.
La bellezza di usare questo approccio è - possiamo usare gli stessi nomi di metodo che abbiamo usato nell'oggetto About e non avremo conflitti. Questo perché questi metodi sono legati a quelli dell'oggetto prototipo stesso, non lo spazio dei nomi globale. Questo semplifica il nostro codice e consente una sorta di "modello" per lo scripting futuro.
Una volta creati gli oggetti, chiamarli è semplice. Non è più necessario dipendere dal framework per attivare eventi quando il documento è caricato o pronto. Ora puoi semplicemente istanziare il tuo oggetto e i suoi eventi saranno vincolati ed eseguiti secondo necessità. Quindi, istanziamo il nostro Di
oggetto:
All'interno della tua vista, dove chiameresti script specifici della tua vista (dipende dalla tua lingua dei template), chiama semplicemente una nuova istanza del tuo oggetto e includi il file come segue:
Come puoi vedere, ho passato il titolo della pagina per la vista (che può essere qualsiasi argomento per qualsiasi necessità - anche Dati modello. Questo ti offre un contesto eccellente sui dati del tuo modello e ti consente di manipolare i dati in JavaScript molto facilmente.
Proprio come il tuo Di
Oggetto, chiamare le tue viste parziali è altrettanto facile. Consiglio vivamente di chiamare nuove istanze degli oggetti JavaScript con vista parziale all'interno del costruttore dell'oggetto: ciò garantisce che le chiamate solo quando necessario e che siano collettivamente in un unico punto.
var About = function (pageTitle) this.pageTitle = pageTitle; // assegnando una nuova istanza della Vista parziale della sidebar da riferire successivamente this.sidebar = new pSidebar (pageTitle); // NOTA: se non hai bisogno di fare riferimento a una vista parziale dopo il fatto, // puoi semplicemente istanziare un'istanza di essa senza assegnarla all'interno del costruttore dell'oggetto, in questo modo: new pSidebar (pageTitle); // facendo lo stesso per il Piè di pagina parziale Visualizza this.footer = new pFooter (); // associa gli eventi non appena l'oggetto viene istanziato this.bindEvents (); ;
Come puoi vedere, facendo riferimento all'oggetto Sidebar come proprietà locale dell'oggetto About, ora associamo quell'istanza, che è un comportamento molto naturale - questa istanza è ora la sidebar della pagina About..
Se non hai bisogno di fare riferimento a una vista parziale dopo il fatto, puoi semplicemente istanziare un'istanza di essa senza assegnarla all'interno del costruttore dell'oggetto, in questo modo:
var About = function (pageTitle) this.pageTitle = pageTitle; nuova pSidebar (pageTitle); // associa gli eventi non appena l'oggetto viene istanziato this.bindEvents (); ;
Da qui, tutto ciò che dobbiamo fare è aggiungere un altro script ai nostri script chiamati nella nostra vista:
Una volta che questa struttura è a posto, possiamo quindi personalizzare il nostro oggetto JavaScript per abbinare la nostra vista e applicare i metodi necessari a quell'oggetto per mantenere l'ambito. Creando un oggetto parallelo alla vista e lavorando sul prototipo dell'oggetto, vediamo i seguenti vantaggi:
Dato che MVC Design Pattern continua a diventare più popolare nel mondo del design, lo sviluppo di oggetti JavaScript per accompagnare la manipolazione del DOM Element cambierà in modo più mirato alla manipolazione specifica della vista e all'evento. Personalizzando i nostri oggetti JavaScript per creare un'istanza in parallelo con le nostre viste, possiamo avere una relazione di stato mano-in-mano tra i due, che è similmente di buon gusto, facile da gestire, semplice da mantenere e perfetto per l'espansione come la vista cresce o cambia, creando una relazione permeabile ed espandibile tra markup e scripting.
Utilizzando un prototipo di oggetto, siamo in grado di mantenere un preciso contesto sull'oggetto di scripting della nostra vista ed espandere quell'oggetto con uno stato mentale di sviluppo ripetitivo. Possiamo quindi replicare questo formato attraverso le nostre viste parziali, risparmiandoci tempo, potenza del cervello e rischio di bug e comportamenti imprevisti.