Verwendung des JavaScript-Prototyps mit MVC

In diesem Artikel wird der Prozess der Verwendung von JavaScript aus einer MVC-basierten Perspektive beschrieben, um das DOM zu bearbeiten. Insbesondere werden wir unsere JavaScript-Objekte, ihre Eigenschaften und Methoden sowie ihre Instantiierungen parallel zum beabsichtigten Verhalten unserer Ansichten (was der Benutzer sieht) erstellen..


Betrachten Sie Ihre Ansichten als Objekte, nicht als Seiten

An jedem Punkt der Entwicklung einer Webseite verwenden wir eine Sprache, die entweder die klassenbasierte Entwicklung oder die objektbasierte Entwicklung fördert. In stark typisierten Sprachen wie Java und C # schreiben wir unsere Ansichten normalerweise in Klassen - und geben ihnen Status, Umfang und Kontext. Wenn wir mit Sprachen wie PHP oder neueren Ansichts-Engines wie Razor für ASP.NET arbeiten, können unsere Ansichten einfach aus Markup (HTML / CSS) und Templates bestehen. Dies bedeutet jedoch nicht, dass wir unsere Wahrnehmung ändern müssen, wie sich die Ansicht als ihre eigene Stateful-Entität verhält.

In Views arbeiten wir hauptsächlich mit HTML, das aus verschachtelten Elementen besteht. Diese Elemente haben Attribute, die beschreiben, was ihr semantischer Zweck ist oder wie sie erscheinen, wenn sie gerendert werden. Diese Elemente verfügen dann über untergeordnete oder übergeordnete Elemente, die Kaskadierung (durch CSS) und Block- / Inline-Verhalten erben / bereitstellen. Diese Elemente können natürlich aus einer OOP-Perspektive (Object Oriented Programming) betrachtet werden. Betrachten Sie zum Beispiel das folgende Markup:

 div.container border: 1px fest # 333; Polsterung: 5px; Farbe Rot; 
 

Über unsere Firma

Ergebnis:

Wie Sie oben sehen können, erbte der Header seine Schriftfarben-Eigenschaft von seinem übergeordneten Container, obwohl das CSS-Verhalten der Kaskadierung verwendet wurde. Dieses Verhalten ist dem Konzept der Vererbung in OOP sehr ähnlich. Wir können auch sehen, dass der Header ein untergeordnetes Element des Containers ist und bestimmte Eigenschaften erbt, die auf dem Verhalten des Elements basieren. Wenn wir unsere Elemente aus dieser Perspektive betrachten, haben wir eine bessere Definition dessen, was wir mit unseren Ansichtselementen machen möchten, und können Stile und Funktionalität besser einkapseln.

Innerhalb einer Ansicht werden wir Markup haben. Dieses Markup kann jedoch verschachtelte Teilansichten wie Seitenleisten, eine Kopfzeile, eine Fußzeile, eine rechte (oder linke) Schiene und einen oder mehrere Inhaltsabschnitte enthalten. Alle diese Teilansichten sollten als ihre eigene Entität betrachtet werden, die ihren eigenen Zustand, Kontext und Geltungsbereich haben kann.

"Wenn Sie Ihre Ansichten und Teilansichten als Objekte verstehen, wird das Schreiben des clientseitigen Codes wesentlich vereinfacht."


Dieses Konzept in Ihre Stile und Skripte übersetzen

Viele Entwickler neigen dazu, JavaScript aus einer prozeduralen oder funktionalen Sicht zu schreiben und vernachlässigen oft die natürlichen Tendenzen, die sich bei anblickbasierten Entwicklungsansätzen und bei der parallelen Instanziierung bieten (das Erstellen einer neuen Instanz der Ansicht, während wir eine neue Instanz eines JavaScript erstellen Objekt, das dieser Ansicht entspricht), wenn Sie in MVC Frameworks arbeiten. Es kommt häufig vor, dass ich auf JavaScript-Dateien stoße, die nur eine Methode nach der anderen sind. Obwohl dieses Verhalten funktioniert und allgemein üblich ist, ist es nicht sehr effizient für die Codewartung, das Debugging oder die Erweiterung des aktuellen oder zukünftigen Codes, wenn Sie intensiv mit Ansichten arbeiten.

Befolgen Sie die folgenden allgemeinen Regeln, um dieser Gewohnheit zu entgehen und mit dem Schreiben von besserem Verhaltenscode zu beginnen.

Goldene Regeln für die View-basierte JavaScript-Entwicklung

  • Jede Ansicht, die von einer Aktion auf einem Controller gerendert wird, sollte ein eigenes JavaScript-Objekt haben.
  • Jede in einer Ansicht geladene Teilansicht sollte ein eigenes JavaScript-Objekt haben.
  • Benennen Sie Ihre Objekte genauso wie Ihre Ansichten (oder Teilansichten). Dies wird für Sie und alle anderen Personen, die Ihren Code berühren, sinnvoller.
  • Verwenden Sie den Pascal-Fall für alle Objekte (d. H. Info, Seitenleiste usw.). Ihre Ansichten sollten bereits vorhanden sein. Warum sollten Sie also nicht dasselbe für Ihre JavaScript-Objekte tun??
  • Alle Konstanten dieser Objekte sollten im Konstruktor gespeichert werden. Das heißt, wenn Ihre Ansicht Eigenschaften hat, die in mehreren Methoden verwendet werden, können alle diese Methoden auf diese Eigenschaften zugreifen.
  • Alle Methoden, die in einer Ansicht (oder Teilansicht) aufgerufen werden, sollten an den Prototyp des Objekts gebunden sein, das dieser Ansicht entspricht.
  • Alle Ereignisbindungen für die Ansicht (oder Teilansicht) sollten in der eigenen Methode der Ereignisbindung enthalten sein, die auf dem Prototyp platziert wird.

Betrachten Sie das folgende Diagramm:

Im Allgemeinen erstelle ich Ansichtsspezifische Skripte und Stile und greife dann aus den wichtigsten Stylesheets und Skriptbibliotheken, die ich erstellt habe, aus, die in vielen Ansichten verwendet werden sollten. Dies reduziert auch die Menge an verwendetem Code.


Sichtbasierte Objekte erstellen

In diesem Artikel legen wir die Struktur für die Seite "Über uns" auf einer MVC-basierten Site fest. Zu Beginn erstellen wir die Struktur wie oben im vorherigen Diagramm gezeigt. Von dort aus erstellen wir ein About-Objekt und beginnen, dem Prototyp Methoden hinzuzufügen. Betrachten Sie zunächst das folgende visuelle Layout:

Dies ist ein sehr logisches und häufig verwendetes Layout für eine Webseite. Wir können unsere Seite in einzelne visuelle Objekte unterteilen. Für jede dieser Ansichten können wir ein logisches Objekt erstellen, das diesem entspricht. Ich lasse im Allgemeinen die sich wiederholenden Informationen in dem Dateinamen oder Klassennamen weg, die von MVC verwendet werden, um den URI aus der Route zu ermitteln, und bleiben stattdessen bei etwas, das leicht konsistent zu halten ist.

Für Seitenaufrufe rufe ich meine JavaScript-Objekte im Allgemeinen mit dem Namen der Ansicht auf. Hier ist ein Beispiel meines AboutView-Objekts:

 // Dateiname anzeigen: AboutView.cs (.NET MVC 1.0), About.cshtml (.NET MVC 3.0) oder AboutView.php (PHP) var About = function (pageTitle) this.pageTitle = pageTitle; // Ereignisse binden, sobald das Objekt instanziiert ist this.bindEvents (); ;

Im obigen Beispiel haben wir ein JavaScript-Objekt im Funktionsformat erstellt, das es ihm ermöglicht, als Objektkonstruktor für alle für die about-Ansicht aufgerufenen Methoden zu dienen. Durch die Wahl dieses Formats können wir eine neue Instanz von diese, Genauso wie wir es mit unserer Sicht Server-Side (sprich new AboutView ();). Von hier aus können wir diesem Objekt Eigenschaften und Methoden zuweisen. Um diesem Objekt Methoden zuzuweisen, benötigen wir Zugriff auf den Prototyp des Objekts.


Der Prototyp von JavaScript ist dein Freund

Entwickler werden oft durch die Elusivität (und Mehrdeutigkeit) des JavaScript-Objektprototyps vereitelt.

Entwickler werden oft durch die Elusivität (und Mehrdeutigkeit) des JavaScript-Objektprototyps vereitelt. Für viele kann es verwirrend sein, sie zu verwenden und zu verstehen, und fügt dem Codieren eine weitere Dimension hinzu. Da JavaScript mit HTML5-, AJAX- und Web 2.0-Konzepten stärker ereignisgesteuert wird, neigt JavaScript dazu, sich auf eine prozessuale Entwicklung zu stützen, die einfach zu entwickeln ist, aber schwer zu warten, zu skalieren und zu replizieren ist.

Denken Sie an das Wort Prototyp als Missverständnis vorerst. Wenn ich denke Prototyp, Ich denke an einen "groben Entwurf" oder eine Basis für die Vererbung, aber das ist nicht genau der Fall.

"In der Realität wäre die bessere Perspektive für Prototype der Zeiger des Objekts im Speicher."

Wenn wir ein Objekt erstellen, instantiieren wir dann eine neue Instanz davon. Wenn wir das tun, erstellen wir einen Ort im Speicher, auf den das Objekt referenziert werden kann (Denken Sie daran, dass sich Objekte in JavaScript befinden Referenztypen, keine primitiven Typen; Wenn Sie eine andere Variable erstellen, die diesem Objekt entspricht, und dann dessen Werte ändern, wird das ursprüngliche Objekt im Zeiger tatsächlich geändert. Wenn Sie ein Objekt erstellen, instanziieren Sie eine neue Instanz davon und ändern Sie dann den "Pointer" oder Prototyp, Wir fügen diesem Objekt direkt Felder und Methoden hinzu (natürlich möchten wir all diese Dinge vor der Instantiierung hinzufügen)..

Hier ist ein Beispiel für das Erstellen von Methoden auf der Über Objektprototyp:

 var About = Funktion (Seitentitel) this.pageTitle = Seitentitel; // Ereignisse binden, sobald das Objekt instanziiert ist this.bindEvents (); ; var About.prototype.bindEvents = function () // Aktueller Kontext: 'this' ist das About-Objekt // Platziere alle Event-Bindungen an einer Stelle und rufe sie // in ihren eigenen Methoden nach Bedarf auf. $ ('ul.menu'). on ('click', 'li.search', $ .proxy (this.toggleSearch, this)); ; var About.prototype.toggleSearch = function (e) // Suchfunktion auf der Seite umschalten;

Wie Sie oben sehen können, haben wir die Eigenschaften des About-Objekts innerhalb des Konstruktors enthalten. Sie haben einen einzigen Bezugspunkt für das Binden von Ereignissen erstellt (in diesem Fall verwenden wir jQuery zum Erstellen der Ereignisbindungen. Sie können jedoch ein beliebiges Framework oder verwenden JavaScript selbst) und haben die toggleSearch-Methode in den Prototyp des About-Objekts eingefügt, um diese Methode für dieses Objekt zu enthalten. Wir haben auch das angerufen bindEvents () Methode im Objekt, so dass es bei der Instantiierung aufgerufen wird.

Betrachten Sie nun den folgenden Code für die Seitenleisten-Teilansicht:

 var pSidebar = function (pageTitle) this.pageTitle = pageTitle; // Aufruf der bindEvents-Methode bei Instantiierung des pSidebar-Objekts. // Dadurch werden die Ereignisse an das Objekt gebunden. this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // aktueller Kontext: 'this' ist das Sidebar-Objekt $ ('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) // umschalten der Untermenüs // aktueller Kontext: 'this' ist die pSidebar obj;

HINWEIS: Ich habe das Objekt angerufen pSidebar denn das ist ein Teilansicht, keine vollständige Ansicht. Dies ist meine Präferenz, zwischen den beiden zu unterscheiden, macht aber die Dinge klarer.

Das Schöne an dieser Methode ist, dass wir dieselben Methodennamen verwenden können wie im About-Objekt, und es werden keine Konflikte auftreten. Dies liegt daran, dass diese Methoden an die Objekte des Objekts gebunden sind Prototyp selbst, nicht der globale Namespace. Dies vereinfacht unseren Code und ermöglicht eine Art "Vorlage" für zukünftige Skripte.


Instanziieren Sie nur nach Bedarf

Sobald Sie Ihre Objekte erstellt haben, ist der Aufruf einfach. Sie müssen sich nicht mehr auf Ihr Framework verlassen, um Ereignisse auszulösen, wenn Ihr Dokument geladen oder bereit ist. Jetzt können Sie Ihr Objekt einfach instanziieren und seine Ereignisse werden nach Bedarf gebunden und ausgeführt. Lassen Sie uns also unser Instanziieren Über Objekt:

Rufen Sie in Ihrer Ansicht, in der Sie Ihre Ansichtsspezifische Skripte aufrufen würden (abhängig von Ihrer Schabloniersprache), einfach eine neue Instanz Ihres Objekts auf und fügen Sie die Datei wie folgt hinzu:

  

Wie Sie sehen können, habe ich den Seitentitel für die Ansicht übergeben (dies kann jedes Argument sein - sogar.) Modelldaten. Dadurch haben Sie einen hervorragenden Kontext zu Ihren Modelldaten und können diese Daten in JavaScript sehr einfach bearbeiten.

Genau wie dein Über Objekt, das Aufrufen Ihrer Teilansichten ist genauso einfach. Ich würde dringend empfehlen, neue Instanzen Ihrer partiellen Ansichts-JavaScript-Objekte innerhalb des Konstruktors des Objekts aufzurufen. Dadurch wird sichergestellt, dass Sie diese nur bei Bedarf aufrufen und sich kollektiv an einem Ort befinden.

 var About = Funktion (Seitentitel) this.pageTitle = Seitentitel; // Zuweisen einer neuen Instanz der Seitenleisten-Teilansicht, auf die später verwiesen werden soll this.sidebar = new pSidebar (pageTitle); // ANMERKUNG: Wenn Sie nach dem Faktum nicht auf eine Teilansicht verweisen müssen, // können Sie einfach eine Instanz davon erstellen, ohne sie innerhalb des Konstruktors des Objekts zuzuweisen. New pSidebar (pageTitle); // dasselbe für die Teilfußzeile tun View this.footer = new pFooter (); // Ereignisse binden, sobald das Objekt instanziiert ist this.bindEvents (); ;

Wie Sie sehen, binden wir nun durch das Verweisen auf das Sidebar-Objekt als lokale Eigenschaft des About-Objekts diese Instanz. Dies ist ein sehr natürliches Verhalten - diese Instanz ist jetzt die Sidebar der About-Seite.

Wenn Sie nach dem Faktieren keine Teilansicht referenzieren müssen, können Sie einfach eine Instanz davon erstellen, ohne sie innerhalb des Konstruktors des Objekts zuzuweisen.

 var About = Funktion (Seitentitel) this.pageTitle = Seitentitel; neue pSidebar (pageTitle); // Ereignisse binden, sobald das Objekt instanziiert ist this.bindEvents (); ;

Jetzt müssen wir nur noch ein Skript zu unseren Skripten hinzufügen, die in unserer Ansicht aufgerufen werden:

   

Warum diese Technik von Vorteil ist

Sobald diese Struktur vorhanden ist, können wir unser JavaScript-Objekt an unsere Ansicht anpassen und die erforderlichen Methoden auf dieses Objekt anwenden, um den Gültigkeitsbereich zu erhalten. Wenn Sie ein viewparalleles Objekt erstellen und den Prototyp dieses Objekts bearbeiten, sehen Sie die folgenden Vorteile:

  1. Die Nomenklatur erleichtert die Navigation durch den Code
  2. Wir benennen unsere Objekte natürlich mit einem Namensraum, wodurch der Bedarf an langen Methodennamen und zu viel Verwendung anonymer Schließung reduziert wird.
  3. Wenig bis kein Konflikt in anderem Code, da unsere Methoden auf dem Prototyp des Objekts und nicht auf globaler Ebene basieren
  4. Wenn Sie unsere Teilansichten im Objektkonstruktor unserer Ansicht instanziieren und einer lokalen Variablenreferenz zuweisen, erstellen wir effektiv eine lokal gebundene Kopie des Objekts dieser Teilansicht.
  5. Wir haben eine feste Definition des Kontextes und können das Schlüsselwort 'this' bedenkenlos verwenden.
  6. Das Debugging wird klar, da alle im Stapel angezeigten Methoden an einer Stelle gebunden sind.

Fazit

Da das MVC-Entwurfsmuster in der Designwelt immer beliebter wird, wird sich die Entwicklung von JavaScript-Objekten zur Begleitung der DOM-Element-Manipulation dahingehend ändern, dass sie stärker auf Ansichts- und Ereignisspezifische Manipulation zugeschnitten ist. Indem Sie unsere JavaScript-Objekte so anpassen, dass sie parallel zu unseren Ansichten instanziiert werden, können wir eine zuständige Beziehung zwischen den beiden Hand-in-Hand-Beziehungen eingehen - eine, die sympathisch im guten Geschmack ist, leicht durchzugehen, einfach zu warten und ideal für die Erweiterung ist Die Ansicht wächst oder ändert sich und schafft eine durchlässige und erweiterbare Beziehung zwischen Markup und Scripting.

Durch die Verwendung eines Prototyps eines Objekts können wir einen präzisen Kontext für das Skriptobjekt unserer Ansicht beibehalten und dieses Objekt mit einem sich wiederholenden Entwicklungsgeist erweitern. Wir können dieses Format dann durch unsere Teilansichten replizieren, wodurch wir Zeit, Gehirnleistung und das Risiko von Fehlern und unerwartetem Verhalten sparen.