Bruke JavaScript's Prototype med MVC

I denne artikkelen vurderer vi prosessen med å bruke JavaScript, fra et MVC-basert perspektiv, for å manipulere DOM. Nærmere bestemt vil vi konstruere våre JavaScript-objekter, deres egenskaper og metoder, og deres instanser parallelt med den hensiktlige oppførelsen av våre visninger (hva brukeren ser).


Vurder dine synspunkter som objekter, ikke som sider

Når som helst i utviklingen av en nettside, bruker vi et språk som naturlig fremmer enten klassebasert utvikling eller objektbasert utvikling. I sterke typede språk som Java og C # skriver vi vanligvis våre synspunkter i klasser - gir dem status, omfang og kontekst. Når vi jobber med språk som PHP eller nyere visningsmotorer, som Razor for ASP.NET, kan våre synspunkter ganske enkelt være markup (HTML / CSS) blandet med templering. Dette betyr imidlertid ikke at vi må endre vår oppfatning av hvordan visningen oppfører seg som sin egen statlige enhet.

Innenfor Visninger jobber vi primært med HTML, som består av nestede elementer; disse elementene har attributter som beskriver hva deres semantiske formål er eller hvordan de vises når de gjengis. Disse elementene har da barn eller foreldreelementer som arver / gir cascading (gjennom CSS) og blokk / inline oppførsel. Disse elementene kan naturlig sett ses fra et OOP (Object Oriented Programming) perspektiv. Tenk for eksempel følgende oppslag:

 div.container border: 1px solid # 333; polstring: 5px; fargen rød; 
 

Om selskapet vårt

Resultat :

Som du kan se over, hovet overskriften sin skrifttypefargeegenskap fra sin overordnede beholder, selv om CSS-oppførelsen av cascading. Denne oppførselen er ganske lik konseptet med arv i OOP. Vi kan også se at toppteksten er et barn av beholderen, arve bestemte egenskaper, basert på elementets oppførsel. Når vi ser våre elementer fra dette perspektivet, har vi en bedre definisjon av hva vi har til hensikt å gjøre med visningselementene våre og kan innkapslere stiler og funksjonalitet bedre.

Innenfor en visning vil vi få oppslag. Denne oppslaget kan imidlertid ha nestede delvise visninger som sidebjelker, en topptekst, en bunntekst, en høyre (eller venstre) skinne og en eller flere innholdsseksjoner. Alle disse delvise synspunktene bør sees som deres egen enhet, i stand til å ha sin egen tilstand, kontekst og omfang.

"Når du tenker på dine synspunkter og delvise syn som objekter, gjør det å skrive klient-side-koden mye lettere."


Oversette dette konseptet til stilene dine og skriptene

Mange utviklere har en tendens til å skrive JavaScript fra et prosessorisk eller funksjonelt synspunkt, og forsømmer ofte å vurdere de naturlige tendensene som tilbys i visningsbaserte utviklingsmetoder og parallell instantiation (opprette en ny forekomst av visningen når vi lager en ny forekomst av en JavaScript objekt som svarer til den visningen) når du arbeider i MVC-rammer. Det er ofte tilfelle at jeg kjører inn i JavaScript-filer som bare er en metode etter hverandre. Selv om denne oppførselen fungerer, og er vanlig, er den ikke veldig effektiv for kodevedlikehold, feilsøking eller utvidelse av nåværende eller fremtidige kode når du arbeider mye med visninger.

For å komme vekk fra denne vanen og begynne å skrive bedre atferdskode, følg disse generelle regler når du begynner å legge ut View's skript og stiler:

Golden Rules of View-basert JavaScript-utvikling

  • Hvert syn som gjengis fra en handling på en kontroller skal ha sitt eget JavaScript-objekt.
  • Hver delvisning som er lastet inne i en visning, skal ha sitt eget JavaScript-objekt.
  • Oppgi navnene dine på samme måte som dine synspunkter (eller delvise synspunkter). Dette vil gi mer mening for deg og alle andre som berører koden din.
  • Bruk Pascal-saken til alle objekter (dvs. Om, Sidebar, etc.). Dine synspunkter bør allerede, så hvorfor ikke gjør det samme for JavaScript-objektene dine?
  • Alle konstanter av disse gjenstandene skal lagres i konstruktøren. Dette betyr at hvis visningen din har egenskaper som vil bli brukt i flere metoder, kan disse metodene alle få tilgang til disse egenskapene.
  • Alle metoder som skal kalles på en visning (eller delvis visning) burde være bundet til prototypen til objektet som tilsvarer den visningen.
  • Alle hendelsesbindinger for visningen (eller delvis visning) skal være inneholdt i sin egen hendelse bindende metode, som er plassert på prototypen.

Vurder følgende diagram:

Jeg lager vanligvis visningsspesifikke skript og stiler, og deretter tar jeg med det jeg trenger fra de viktigste stilarkene og skriptbibliotekene jeg har opprettet, som vil bli brukt på mange visninger. Dette reduserer også mengden kode som brukes.


Opprette visningsbaserte objekter

I denne artikkelen legger vi ut strukturen for Om oss-siden på et MVC-basert nettsted. For å starte, vil vi opprette strukturen som vist ovenfor i det forrige diagrammet. Derfra vil vi opprette et Om objekt, og begynne å legge til metoder til prototypen. Først bør du vurdere følgende visuelle layout:

Dette er en veldig logisk og vanlig layout for en nettside. Vi kan segmentere vår side i separate visuelle objekter. For hver av disse visningene kan vi opprette et logisk objekt som tilsvarer det. Jeg utelater vanligvis den repeterende informasjonen i filnavnet eller klassenavnet som brukes av MVC for å bestemme URI fra ruten og i stedet holde fast i noe som er lett å holde konsekvent.

For sidevisninger kaller jeg vanligvis JavaScript-objektene mine med navnet på visningen. Her er et eksempel på min OmView-objekt:

 // Se filnavn: AboutView.cs (. NET MVC 1.0), About.cshtml (. NET MVC 3.0), eller AboutView.php (PHP) var Om = funksjon (pageTitle) this.pageTitle = pageTitle; // bindende hendelser så snart objektet er instantiated this.bindEvents (); ;

I eksempelet ovenfor har vi opprettet et JavaScript-objekt i funksjonsformatet, noe som gir kapasiteten til å fungere som en Objekt-konstruktør for alle metoder som kreves for omvisningen. Ved å velge dette formatet kan vi instantiere en ny forekomst av dette, akkurat som vi gjør med vår visning Server-Side (ved å si Ny OmView ();). Herfra kan vi tilordne egenskaper og metoder til dette objektet. For å tilordne metoder til dette objektet trenger vi tilgang til objektets prototype.


JavaScript's Prototype er din venn

Utviklere er ofte imot av elusiveness (og tvetydighet) av JavaScript Object Prototype.

Utviklere er ofte imot av elusiveness (og tvetydighet) av JavaScript Object Prototype. For mange kan det være forvirrende å bruke og forstå og legger til en annen dimensjon til koding. Siden JavaScript blir mer hendelsesdrevet med HTML5, AJAX og web 2.0 konsepter, har JavaScript en tendens til å lene seg naturlig til prosessutvikling som er lett å utvikle, men vanskelig å vedlikeholde, skalere og replikere.

Tenk på ordet prototype som misnomer for nå. Når jeg tenker prototype, Jeg tenker på et "grovt utkast" eller en base for arv, men dette er ikke akkurat tilfelle.

"I virkeligheten er det bedre perspektivet for prototype objektets peker i minnet."

Når vi lager et objekt, instanser vi en ny forekomst av den. Når vi gjør det, lager vi et sted i minnet om at objektet kan refereres (husk, objekter i JavaScript er referansetyper, ikke primitive typer; oppretter en annen variabel som er lik den objekten, og da endrer dens verdier vil faktisk endre det opprinnelige objektet i pekeren). Når vi lager et objekt, skal du instansere en ny forekomst av den, og deretter endre dens "Pointer," eller prototype, vi legger til felt og metoder til det objektet i minnet direkte (selvfølgelig vil vi legge til alle disse tingene før instantiation).

Her er et eksempel på å lage metoder på Handle om objektets prototype:

 var om = funksjon (pageTitle) this.pageTitle = pageTitle; // bindende hendelser så snart objektet er instantiated this.bindEvents (); ; var About.prototype.bindEvents = function () // Nåværende kontekst: 'dette' er Om-objektet // Plasser alle hendelsesbindingene på ett sted og ring dem ut // i egne metoder etter behov. $ ('ul.menu'). på ('klikk', 'li.search', $ .proxy (this.toggleSearch, dette)); ; var About.prototype.toggleSearch = funksjon (e) // Veksle søkefunksjonen på siden;

Som du kan se over, har vi inneholdt egenskapene til Om-objektet i konstruktøren, har opprettet et enkelt referansepunkt for bindende hendelser (i dette tilfellet bruker vi jQuery til å skape hendelsesbindingene, men du kan bruke et hvilket som helst rammeverk eller JavaScript selv), og har plassert toggleSearch-metoden på prototypen til Om-objektet for å inneholde den metoden for den objekten. Vi har også kalt bindEvents () metode i objektet slik at det kalles instantiation.

Nå kan du vurdere følgende kode for sidebarens delvisning:

 var pSidebar = funksjon (pageTitle) this.pageTitle = pageTitle; // ring bindEvents-metoden ved instantiering av pSidebar-objektet. // dette vil binde hendelsene til objektet this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // nåværende kontekst: 'dette' er sidefeltobjektet $ ('ul.menu'). på ('klikk', 'li.has-undermeny', $ .proxy this.toggleSubMenu, dette)); $ ('input # search'). på ('klikk', $ .proxy (this.openSearch, this)); ; var pSidebar.prototype.toggleSubMenu = funksjon (e) // bytte undermenyer // nåværende kontekst: 'dette' er pSidebar obj;

MERK: Jeg ringte objektet pSidebar fordi dette er en delvis visning, ikke en full visning. Dette er min preferanse for å skille mellom de to, men gjør ting klarere.

Skjønnheten ved å bruke denne tilnærmingen er - vi kan bruke de samme metodene som vi brukte i Om-objektet, og vi vil ikke ha noen konflikter. Dette skyldes at disse metodene er bundet til objektets prototype i seg selv, ikke det globale navneområdet. Dette forenkler koden vår og gir mulighet for en slags "templering" for fremtidig skripting.


Instantiate bare som nødvendig

Når du har opprettet objekter, er det enkelt å ringe dem. Ikke lenger trenger du å stole på rammen din for å brenne hendelser når dokumentet er lastet eller klart. Nå kan du bare ordne objektet ditt og hendelsene blir bundet og utført etter behov. Så la oss instansere våre Handle om gjenstand:

Innenfor visningen din hvor du vil ringe visningsspesifikke skript (avhengig av ditt templerende språk), ring bare en ny forekomst av objektet ditt og ta med filen som følger:

  

Som du ser, passerte jeg i sidetittelen for visningen (som kan være noe argument for ethvert behov - jevnt Modelldata. Dette gir deg utmerket sammenheng over modelldataene dine og lar deg manipulere dataene i JavaScript veldig enkelt.

Akkurat som din Handle om Objekt, ringe dine delvise synspunkter er like enkelt. Jeg anbefaler på det sterkeste å kalle nye forekomster av dine delvise JavaScript-objekter i objektets konstruktør - dette sikrer at du bare ringer etter behov og at de er samlet på ett sted.

 var om = funksjon (pageTitle) this.pageTitle = pageTitle; // tilordne en ny forekomst av Sidebar Partial View som refereres senere this.sidebar = new pSidBar (pageTitle); // MERK: Hvis du ikke trenger å referere til en delvis visning etter det faktum, // kan du bare ordne en forekomst av den uten å tilordne den i objektets konstruktør, som det er: Ny pSidBar (pageTitle); // gjør det samme for den delvise footeren View this.footer = new pFooter (); // bindende hendelser så snart objektet er instantiated this.bindEvents (); ;

Som du kan se, ved å referere til Sidebar-objektet som en lokal egenskap for Om-objektet, binder vi nå det forekomsten, noe som er en veldig naturlig oppførsel - denne forekomsten er nå Om sidens sidebjelke.

Hvis du ikke trenger å referere til en delvis visning etter det faktum, kan du bare instansere en forekomst av den uten å tilordne den i objektets konstruktør, slik:

 var om = funksjon (pageTitle) this.pageTitle = pageTitle; Ny pSidBar (sideTitle); // bindende hendelser så snart objektet er instantiated this.bindEvents (); ;

Herfra, alt vi trenger å gjøre er å legge til et annet skript til våre skript kalt i vårt syn:

   

Hvorfor denne teknikken er gunstig

Når denne strukturen er på plass, kan vi deretter skreddersy JavaScript-objektet for å matche visningen vår og bruke de nødvendige metodene til objektet for å opprettholde omfanget. Ved å opprette et visnings-parallell objekt og arbeider av prototypen for objektet ser vi følgende fordeler:

  1. Nomenklaturen gjør det enklere å navigere gjennom kode
  2. Vi navngir naturligvis våre objekter, reduserer behovet for lange metodenavn og for mye bruk av anonym nedleggelse.
  3. Liten eller ingen konflikt i annen kode fordi våre metoder er på prototypen av objektet, ikke på global nivå
  4. Når vi instanserer våre partielle visninger i objektets konstruktør for Vis og tilordner dem til en lokal variabelreferanse, oppretter vi effektivt en lokalt bundet kopi av den delenes visningsobjekt.
  5. Vi har en fast definisjon av kontekst og kan bruke søkeordet 'dette' uten å bekymre deg.
  6. Feilsøking blir klar fordi alle metodene som vises i stabelen er bundet på ett sted.

Konklusjon

Siden MVC Design Pattern fortsetter å bli mer populært i designverdenen, vil utviklingen av JavaScript-objekter som følger DOM Element-manipulasjon, endres for å være skreddersydd mot visningsspesifikke og hendelsespesifikke manipulasjoner. Ved å skreddersy JavaScript-objektene våre for å skape parallell med våre Visninger, kan vi få et håndholdt forhold mellom de to - en som er symantisk i god smak, lett å gjennomgå, enkel å vedlikeholde og perfekt for ekspansjon som Visningen vokser eller endres, og skaper et permeabelt og utvidbart forhold mellom markup og scripting.

Ved å utnytte et objekts prototype, kan vi opprettholde en presis kontekst på vårt Sees skriptobjekt og utvide det objektet med en gjentakende utviklingsramme. Vi kan da kopiere dette formatet gjennom våre delvise synspunkter, og sparer tid, hjernekraft og risiko for feil og uventet oppførsel.