Het prototype van JavaScript gebruiken met MVC

In dit artikel zullen we het gebruik van JavaScript vanuit een MVC-perspectief bekijken om de DOM te manipuleren. Meer specifiek zullen we onze JavaScript-objecten, hun eigenschappen en methoden, en hun instantiaties parallel aan het beoogde gedrag van onze Views (wat de gebruiker ziet) ontwikkelen.


Beschouw uw weergaven als objecten, niet als pagina's

Op elk moment in de ontwikkeling van een webpagina gebruiken we een taal die van nature op klassen gebaseerde ontwikkeling of objectgebaseerde ontwikkeling bevordert. In sterk getypte talen zoals Java en C # schrijven we onze standpunten gewoonlijk in klassen - en geven ze status, reikwijdte en context. Wanneer we werken met talen zoals PHP of nieuwere weergavemotoren, zoals Razor voor ASP.NET, kunnen onze weergaven eenvoudigweg opmaak (HTML / CSS) zijn, vermengd met sjabloneren. Dit betekent echter niet dat we onze perceptie over hoe het beeld zich gedraagt ​​als zijn eigen stateful entiteit moeten veranderen.

Binnen Views werken we voornamelijk met HTML, die bestaat uit geneste elementen; deze elementen hebben attributen die beschrijven wat hun semantische doel is of hoe ze verschijnen wanneer ze worden weergegeven. Deze elementen hebben dan kinderen of bovenliggende elementen die cascadering (via CSS) erven / bieden en blokkeren / inline gedrag vertonen. Deze elementen kunnen natuurlijk worden bekeken vanuit een OOP (Object-Oriented Programming) perspectief. Overweeg bijvoorbeeld de volgende markup:

 div.container border: 1px solid # 333; opvulling: 5px; kleur rood; 
 

Over ons bedrijf

Resultaat :

Zoals je hierboven kunt zien, heeft de header de eigenschap font-kleur overgenomen van de bovenliggende container door het CSS-gedrag van trapsgewijze. Dit gedrag lijkt erg op het concept van overerving in OOP. We kunnen ook zien dat de header een child van de container is, die bepaalde eigenschappen overneemt, gebaseerd op het gedrag van het element. Wanneer we onze elementen vanuit dit perspectief bekijken, hebben we een betere definitie van wat we met onze weergave-elementen van plan zijn en kunnen we stijlen en functionaliteit beter inkapselen.

In een weergave hebben we markup. Deze opmaak kan echter geneste gedeeltelijke aanzichten hebben zoals zijbalken, een koptekst, een voettekst, een rechter (of linker) rail en een of meer inhoudsecties. Al deze deelweergaven moeten worden gezien als hun eigen entiteit, in staat om hun eigen status, context en reikwijdte te hebben.

"Wanneer u uw weergaven en gedeeltelijke visies opvat als objecten, wordt het schrijven van uw client-side code veel eenvoudiger."


Dit concept vertalen naar uw stijlen en scripts

Veel ontwikkelaars hebben de neiging om JavaScript vanuit een procedureel of functioneel oogpunt te schrijven en vergeten vaak de natuurlijke tendensen die worden geboden in op weergave gebaseerde ontwikkelingsbenaderingen en parallelle instantiatie (een nieuw exemplaar van de weergave te maken terwijl we een nieuw exemplaar van een JavaScript maken) object dat met die weergave overeenkomt) bij het werken in MVC Frameworks. Het komt vaak voor dat ik JavaScript-bestanden tegenkom die maar één methode na de andere zijn. Hoewel dit gedrag werkt en gebruikelijk is, is het niet erg efficiënt voor code-onderhoud, foutopsporing of uitbreiding van huidige of toekomstige code wanneer u uitgebreid met weergaven werkt.

Om deze gewoonte te omzeilen en te beginnen met het schrijven van betere gedragscode, moet je deze algemene regels volgen wanneer je begint met het opmaken van de scripting en stijlen van je View:

Gouden regels van op weergave gebaseerde JavaScript-ontwikkeling

  • Elke weergave die wordt weergegeven door een actie op een controller, moet zijn eigen JavaScript-object hebben.
  • Elke gedeeltelijke weergave die in een weergave is geladen, moet een eigen JavaScript-object hebben.
  • Geef uw objecten dezelfde naam als uw views (of gedeeltelijke views). Dit zal logischer zijn voor u en alle anderen die uw code aanraken.
  • Gebruik Pascal-hoes voor alle objecten (bijv. Over, Zijbalk, enz.). Uw mening zou al moeten bestaan, dus waarom niet hetzelfde doen voor uw JavaScript-objecten?
  • Alle constanten van deze objecten moeten worden opgeslagen in de constructor. Dit betekent dat als uw weergave eigenschappen heeft die in meerdere methoden worden gebruikt, deze methoden allemaal toegang hebben tot deze eigenschappen.
  • Alle methoden die in een weergave (of gedeeltelijke weergave) worden aangeroepen, moeten worden gebonden aan het prototype van het object dat met die weergave overeenkomt.
  • Alle gebeurtenisbindingen voor de weergave (of gedeeltelijke weergave) moeten worden opgenomen in de methode voor het binden van hun eigen gebeurtenis, die op het prototype wordt geplaatst.

Beschouw het volgende diagram:

Ik maak over het algemeen beeldspecifieke scripts en stijlen en pak vervolgens wat ik nodig heb uit de belangrijkste stylesheets en scriptbibliotheken die ik heb gemaakt en die op veel weergaven zouden worden gebruikt. Dit vermindert ook de hoeveelheid code die wordt gebruikt.


Op weergave gebaseerde objecten maken

In dit artikel zullen we de structuur voor de About Us-pagina op een MVC-gebaseerde site uiteenzetten. Om te beginnen, zullen we de structuur creëren zoals hierboven getoond in het vorige diagram. Van daaruit maken we een About-object en beginnen we met het toevoegen van methoden aan het prototype. Overweeg eerst de volgende visuele lay-out:

Dit is een zeer logische en veelgebruikte lay-out voor een webpagina. We kunnen onze pagina opsplitsen in afzonderlijke visuele objecten. Voor elk van deze weergaven kunnen we een logisch object maken dat daarmee correspondeert. Ik laat de repetitieve informatie in de bestandsnaam of classname die wordt gebruikt door MVC over het algemeen weg om de URI van de route te bepalen en in plaats daarvan te plakken met iets dat gemakkelijk consistent te houden is.

Voor paginaweergaven bel ik mijn JavaScript-objecten meestal met de naam van de weergave. Hier is een voorbeeld van mijn AboutView-object:

 // Bekijk bestandsnaam: AboutView.cs (.NET MVC 1.0), About.cshtml (.NET MVC 3.0) of AboutView.php (PHP) var About = function (pageTitle) this.pageTitle = pageTitle; // binding events zodra het object wordt geïnstantieerd this.bindEvents (); ;

In het bovenstaande voorbeeld hebben we een JavaScript-object gemaakt in de functie-indeling, waardoor het de capaciteit heeft om te dienen als een objectconstructor voor alle methoden die zijn vereist voor de over-weergave. Door dit formaat te kiezen, kunnen we een nieuw exemplaar van deze, net zoals wij doen met onze visie Server-kant (door te zeggen nieuw OverView ();). Vanaf hier kunnen we eigenschappen en methoden aan dit object toewijzen. Om methoden aan dit object toe te wijzen, hebben we toegang tot het prototype van het object nodig.


Het Prototype van JavaScript is je vriend

Ontwikkelaars worden vaak gedwarsboomd door de ongrijpbaarheid (en ambiguïteit) van JavaScript's Object Prototype.

Ontwikkelaars worden vaak gedwarsboomd door de ongrijpbaarheid (en ambiguïteit) van JavaScript's Object Prototype. Voor velen kan het verwarrend zijn om te gebruiken en te begrijpen en voegt een andere dimensie toe aan coderen. Omdat JavaScript meer wordt gedreven door gebeurtenissen met HTML5-, AJAX- en web 2.0-concepten, heeft JavaScript de neiging om op natuurlijke wijze te leunen naar procedurele ontwikkeling die gemakkelijk te ontwikkelen is, maar moeilijk te onderhouden, schaalbaar en te repliceren is.

Denk aan het woord Prototype als een verkeerde benaming voor nu. Wanneer ik denk Prototype, Ik denk aan een "ruwe schets" of een basis voor overerving, maar dit is niet precies het geval.

"In werkelijkheid zou het betere perspectief voor Prototype de Pointer van het object in het geheugen zijn."

Wanneer we een object maken, plaatsen we een nieuw exemplaar ervan. Wanneer we dat doen, creëren we een plaats in het geheugen waarin naar het object kan worden verwezen (onthoud, objecten in JavaScript zijn referentietypen, geen primitieve types; het maken van een andere variabele gelijk aan dat object en het vervolgens wijzigen van de waarden zal in feite het oorspronkelijke object in de aanwijzer veranderen). Wanneer we een object maken, een nieuw exemplaar ervan instantiëren en vervolgens de "Aanwijzer", of Prototype, we voegen velden en methoden rechtstreeks toe aan dat object in het geheugen (uiteraard willen we al deze dingen vóór instantiatie toevoegen).

Hier is een voorbeeld van het maken van methoden op de Wat betreft prototype van een object:

 var About = function (pageTitle) this.pageTitle = pageTitle; // binding events zodra het object wordt geïnstantieerd this.bindEvents (); ; var About.prototype.bindEvents = function () // Huidige context: 'dit' is het About-object // Plaats al je event-bindingen op één plek en roep ze naar behoefte // op in hun eigen methoden. $ ('ul.menu'). on ('click', 'li.search', $ .proxy (this.toggleSearch, this)); ; var About.prototype.toggleSearch = function (e) // Schakel de zoekfunctie op de pagina;

Zoals je hierboven kunt zien, hebben we de eigenschappen van het object About in de constructor opgenomen, een enkel referentiepunt gemaakt voor bindende events (in dit geval gebruiken we jQuery om de event-bindingen te maken, maar je kunt elk framework of JavaScript zelf) en hebben de toggleSearch-methode op het prototype van het object About geplaatst om die methode aan dat object te koppelen. We hebben ook de bindEvents () methode in het object zodat deze wordt aangeroepen voor instantiatie.

Overweeg nu de volgende code voor de gedeeltelijke weergave van de zijbalk:

 var pSidebar = function (pageTitle) this.pageTitle = pageTitle; // roep de methode bindEvents op bij het instantiëren van het pSidebar-object. // dit zal de gebeurtenissen binden aan het object this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // huidige context: 'this' is het Sidebar-object $ ('ul.menu'). on ('click', 'li.has-submenu', $ .proxy ( this.toggleSubMenu, this)); $ ('input # search'). on ('klik', $ .proxy (this.openSearch, this)); ; var pSidebar.prototype.toggleSubMenu = functie (e) // schakel de submenu's // huidige context: 'dit' is de pSidebar obj;

NOTITIE: Ik heb het object gebeld pSidebar omdat dit een is gedeeltelijke weergave, geen volledig beeld. Dit is mijn voorkeur om onderscheid te maken tussen de twee, maar maakt de zaken duidelijker.

Het mooie van deze benadering is - we kunnen dezelfde methodamen gebruiken die we gebruikten in het About-object en we zullen geen conflicten hebben. Dit komt omdat deze methoden zijn gebonden aan het object prototype zelf, niet de globale naamruimte. Dit vereenvoudigt onze code en zorgt voor een soort "sjabloneren" voor toekomstige scripting.


Instantiëren alleen als nodig

Nadat u uw objecten hebt gemaakt, is het eenvoudig om ze te bellen. U hoeft niet langer afhankelijk te zijn van uw kader om gebeurtenissen te activeren wanneer uw document is geladen of gereed is. U kunt nu eenvoudig uw object instantiëren en de gebeurtenissen ervan zullen worden gebonden en indien nodig worden uitgevoerd. Laten we dus onze Wat betreft voorwerp:

Binnen uw weergave, waar u uw weergave specifieke scripts zou noemen (afhankelijk van uw sjabloneertaal), roept u eenvoudig een nieuw exemplaar van uw object aan en neemt u het bestand als volgt op:

  

Zoals je kunt zien, heb ik de paginatitel voor de weergave doorgegeven (wat een argument kan zijn voor elke behoefte - zelfs Modelgegevens. Dit geeft je een uitstekende context over je modelgegevens en stelt je in staat om die gegevens heel gemakkelijk te manipuleren in JavaScript.

Net zoals jij Wat betreft Object, het oproepen van je gedeeltelijke visies is net zo eenvoudig. Ik zou het ten zeerste aanbevelen nieuwe exemplaren van uw JavaScript-objecten met gedeeltelijke weergave binnen de constructor van het object aan te roepen - dit zorgt ervoor dat u deze alleen naar behoefte belt en dat ze collectief op één plaats staan.

 var About = function (pageTitle) this.pageTitle = pageTitle; // een nieuwe instantie toewijzen van de zijbalk van de zijbalk waarnaar later moet worden verwezen this.sidebar = new pSidebar (pageTitle); // OPMERKING: als u achteraf niet naar een gedeeltelijke weergave hoeft te verwijzen, // kunt u eenvoudig een instantie ervan instantiëren zonder deze toe te wijzen binnen de constructor van het object, als zodanig: new pSidebar (pageTitle); // hetzelfde doen voor de gedeeltelijke voettekst Bekijk this.footer = new pFooter (); // binding events zodra het object wordt geïnstantieerd this.bindEvents (); ;

Zoals u kunt zien, door het Sidebar-object te verwijzen als een lokale eigenschap van het object About, binden we nu die instantie, wat een heel natuurlijk gedrag is - deze instantie is nu de zijbalk van de Over-pagina.

Als u achteraf niet naar een gedeeltelijke weergave hoeft te verwijzen, kunt u eenvoudig een instantie ervan instantiëren zonder deze toe te wijzen binnen de constructor van het object, zoals:

 var About = function (pageTitle) this.pageTitle = pageTitle; nieuwe pSidebar (pageTitle); // binding events zodra het object wordt geïnstantieerd this.bindEvents (); ;

Vanaf hier is alles wat we moeten doen om nog een script toe te voegen aan onze scripts die naar onze mening worden genoemd:

   

Waarom deze techniek nuttig is

Zodra deze structuur is geïnstalleerd, kunnen we ons JavaScript-object aanpassen aan onze weergave en de benodigde methoden toepassen op dat object om de scope te behouden. Door een view-parallel object te maken en het prototype van dat object uit te werken, zien we de volgende voordelen:

  1. De nomenclatuur maakt het gemakkelijker om door de code te navigeren
  2. We namen onze objecten van nature op in naam, waardoor de behoefte aan lange methodenamennamen en te veel gebruik van anonieme sluiting afnam.
  3. Weinig tot geen conflict in andere code, omdat onze methoden gebaseerd zijn op het prototype van het object, niet op het wereldwijde niveau
  4. Bij het instantiëren van onze deelaanzichten in de objectconstructor van de View en deze toe te wijzen aan een verwijzing naar de lokale variabele, maken we effectief een lokaal gebonden kopie van het object van die Partial View.
  5. We hebben een duidelijke definitie van context en kunnen zonder zorgen het trefwoord 'dit' gebruiken.
  6. Debuggen wordt duidelijk omdat alle methoden die in de stapel worden weergegeven, op één plaats zijn gebonden.

Conclusie

Naarmate het MVC-ontwerppatroon steeds populairder wordt in de ontwerpwereld, zal de ontwikkeling van JavaScript-objecten om DOM-elementmanipulatie te begeleiden, veranderen om meer toegesneden te zijn op weergavespecifieke en gebeurtenisspecifieke manipulatie. Door onze JavaScript-objecten aan te passen om parallel met onze Views te instantiëren, kunnen we een stateful relatie tussen beide hand in hand hebben, een die symantisch goed van smaak is, gemakkelijk te doorlopen, eenvoudig te onderhouden en perfect voor uitbreiding als het beeld groeit of verandert, waardoor een doorlaatbare en uitbreidbare relatie ontstaat tussen markup en scripting.

Door gebruik te maken van het prototype van een object, kunnen we een precieze context behouden op het scripting-object van View, en dat object uitbreiden met een zich herhalend ontwikkelframe-of-mind. We kunnen dit formaat vervolgens repliceren via onze gedeeltelijke weergaven, waardoor we tijd, hersenkracht en het risico op fouten en onverwacht gedrag besparen.