Använda JavaScript-prototypen med MVC

I den här artikeln granskar vi processen med att använda JavaScript, från ett MVC-baserat perspektiv, för att manipulera DOM. Mer specifikt kommer vi att konstruera våra JavaScript-objekt, deras egenskaper och metoder och deras instanser parallellt med vårt visade beteende (vad användaren ser).


Tänk på dina synpunkter som föremål, inte som sidor

Vid varje tillfälle i utvecklingen av en webbsida använder vi ett språk som naturligtvis främjar antingen klassbaserad utveckling eller objektbaserad utveckling. I starkt typade språk som Java och C # skriver vi vanligtvis våra åsikter i klasser - ger dem tillstånd, omfattning och sammanhang. När vi arbetar med språk som PHP eller nyare synmotorer, som Razor för ASP.NET, kan våra synpunkter helt enkelt vara markup (HTML / CSS) blandat med templerande. Men det betyder inte att vi måste ändra vår uppfattning om hur uppfattningen beter sig som sin egen statliga enhet.

Inom Visningar arbetar vi huvudsakligen med HTML, som består av kapslade element; Dessa element har attribut som beskriver vad deras semantiska syfte är eller hur de uppträder när de görs. Dessa element har då barn eller moderelement som ärar / tillhandahåller kaskad (genom CSS) och block / inline-beteenden. Dessa element kan naturligtvis ses från ett OOP-perspektiv (Object Oriented Programming). Tänk till exempel följande markup:

 div.container border: 1px solid # 333; vaddering: 5px; färgen röd; 
 

Om vårt företag

Resultat :

Som du kan se ovan, arvade huvudet sin typsnittsfärgegenskaper från dess förälderbehållare, trots CSS-beteendet hos cascading. Detta beteende är ganska likt begreppet arv i OOP. Vi kan också se att rubriken är ett barn i behållaren, ärvt vissa egenskaper, baserat på elementets beteende. När vi ser våra element ur detta perspektiv har vi en bättre definition av vad vi avser att göra med våra visningselement och kan inkapsla stilar och funktionalitet bättre.

Inuti en vy kommer vi att ha markup. Den här markeringen kan emellertid ha nestade partiella vyer som sidor, en rubrik, en sidfot, en höger (eller vänster) räls och en eller flera innehållsavsnitt. Alla dessa partiella synpunkter bör ses som en egen enhet, som kan ha sin egen stat, sammanhang och omfattning.

"När du tänker på dina åsikter och partiella synpunkter som objekt gör det att skriva din klientsidkod mycket lättare."


Översätta detta begrepp till dina stilar och skript

Många utvecklare brukar skriva JavaScript från en procedurell eller funktionell synvinkel och ofta försumma att överväga de naturliga tendenser som erbjuds i visningsbaserade utvecklingsmetoder och parallell instansering (skapa en ny instans av visningen när vi skapar en ny instans av en JavaScript objekt som motsvarar den vyn) när man arbetar i MVC-ramar. Det är ofta fallet att jag stöter på JavaScript-filer som bara är en metod efter en annan. Även om detta beteende fungerar och är vanligt är det inte särskilt effektivt för kodunderhåll, debugging eller förlängning av nuvarande eller framtida kod när du arbetar i stor utsträckning med visningar.

För att komma bort från denna vana och börja skriva bättre beteendeskod, när du börjar lägga ut dina visnings skript och stilar, följ dessa allmänna regler:

Gyllene regler för visningsbaserad JavaScript-utveckling

  • Varje vy som gjorts av en åtgärd på en kontroller ska ha sitt eget JavaScript-objekt.
  • Varje delvy som laddas in i en vy ska ha sitt eget JavaScript-objekt.
  • Namn dina föremål på samma sätt som dina synpunkter (eller delvisa visningar). Detta kommer att ge större mening för dig och alla andra som berör din kod.
  • Använd Pascal-fallet för alla objekt (dvs. Om, Sidpanel etc.). Dina synpunkter bör redan, så varför inte göra detsamma för dina JavaScript-objekt?
  • Alla konstanter av dessa föremål bör lagras i konstruktören. Det betyder att om dina syn har egenskaper som kommer att användas i flera metoder, kan dessa metoder alla få tillgång till dessa egenskaper.
  • Alla metoder som ska kallas på en vy (eller delvis visning) borde vara bundna till prototypen av objektet som motsvarar den vyn.
  • Alla händelsebindningar för vyn (eller delvy) bör ingå i sin egen händelsebindande metod, som placeras på prototypen.

Tänk på följande diagram:

Jag skapar generellt visningsspecifika skript och stilar och tar sedan upp vad jag behöver från de huvudsakliga stylesheets och manusbibliotek som jag skapat som skulle användas på många visningar. Detta minskar också mängden kod som används.


Skapa visningsbaserade objekt

I den här artikeln lägger vi ut strukturen för sidan Om oss på en MVC-baserad webbplats. För att starta skapar vi strukturen som visas ovan i det föregående diagrammet. Därifrån skapar vi ett Om objekt och börjar lägga till metoder till prototypen. Först överväga följande visuella layout:

Detta är en mycket logisk och vanligt använd layout för en webbsida. Vi kan segmentera vår sida i separata visuella objekt. För vart och ett av dessa synpunkter kan vi skapa ett logiskt objekt som motsvarar det. Jag slipper i allmänhet den repeterande informationen i filnamnet eller klassnamnet som används av MVC för att bestämma URI-filen från rutten och i stället hålla fast vid någonting som är lätt att hålla konsekvent.

För sidvisningar kallar jag generellt mina JavaScript-objekt med namnet på vyn. Här är ett exempel på mitt AboutView-objekt:

 // Visa filnamn: AboutView.cs (. NET MVC 1.0), About.cshtml (. NET MVC 3.0), eller AboutView.php (PHP) var Om = funktion (pageTitle) this.pageTitle = pageTitle; // bindande händelser så snart objektet är instantiated this.bindEvents (); ;

I det ovanstående exemplet skapade vi ett JavaScript-objekt i funktionsformatet, vilket gav det kapacitet att fungera som en objektkonstruktor för alla metoder som kallades för den aktuella vyn. Genom att välja detta format kan vi omedelbara en ny instans av detta, precis som vi gör med vår uppfattning Server-Side (genom att säga ny AboutView ();). Härifrån kan vi tilldela egenskaper och metoder till det här objektet. För att tilldela metoder till det här objektet behöver vi tillgång till objektets prototyp.


JavaScript Prototype är din vän

Utvecklare är ofta förknippade med elusiveness (och tvetydighet) av JavaScript Object Prototype.

Utvecklare är ofta förknippade med elusiveness (och tvetydighet) av JavaScript Object Prototype. För många kan det vara förvirrande att använda och förstå och lägger till en annan dimension för kodning. Eftersom JavaScript blir mer händelsestyrt med HTML5, AJAX och web 2.0-koncept tenderar JavaScript att luta sig naturligt till processutveckling som är lätt att utveckla men svår att underhålla, skala och replikera.

Tänk på ordet Prototyp som en missnöje för nu. När jag tror Prototyp, Jag tänker på ett "grovt utkast" eller en grund för arv, men det här är inte exakt fallet.

"I verkligheten är det bättre perspektivet för prototyp objektets pekare i minnet."

När vi skapar ett objekt instämmer vi sedan en ny instans av den. När vi gör det skapar vi en plats i minnet att objektet kan refereras (kom ihåg att objekt i JavaScript är referenstyper, inte primitiva typer; skapa en annan variabel som är lika med det objektet och sedan ändra dess värden kommer det faktiskt att ändra originalobjektet i pekaren). När vi skapar ett objekt, instansera en ny instans av det och ändra sedan dess "Pointer," eller Prototyp, vi lägger till fält och metoder till det objektet i minnet direkt (självklart vill vi lägga till alla dessa saker före instansering).

Här är ett exempel på att skapa metoder på Handla om objektets prototyp:

 var om = funktion (pageTitle) this.pageTitle = pageTitle; // bindande händelser så snart objektet är instantiated this.bindEvents (); ; var About.prototype.bindEvents = function () // Nuvarande sammanhang: 'this' är Om objektet // Placera alla dina händelsebindningar på ett ställe och kalla dem ut // i egna metoder efter behov. $ ('ul.menu') på ('klicka', 'li.search', $ .proxy (this.toggleSearch, this)); ; var About.prototype.toggleSearch = function (e) // Växla sökfunktionen på sidan;

Som du kan se ovan har vi inneburit egenskaperna hos Om-objektet inom konstruktören, skapat en enda referenspunkt för bindande händelser (i det här fallet använder vi jQuery för att skapa händelsebindningar, men du kan använda ramar eller JavaScript själv), och har placerat metoden ToggleSearch på prototypen av Om-objektet för att innehålla den metoden för det objektet. Vi har också kallat bindEvents () metod i objektet så att det kallas instantiation.

Nu, överväga följande kod för sidopanelen:

 var pSidebar = funktion (pageTitle) this.pageTitle = pageTitle; // kalla bindEvents-metoden vid instansiering av pSidebar-objektet. // detta kommer att binda händelserna till objektet this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // nuvarande kontext: 'this' är Sidebar-objektet $ ('ul.menu'). ((klicka), 'li.has-undermeny', $ .proxy this.toggleSubMenu, detta)); $ ('input # search'). på ('klicka', $ .proxy (this.openSearch, this)); ; var pSidebar.prototype.toggleSubMenu = funktion (e) // byta undermenyer // nuvarande sammanhang: 'detta' är pSidebar obj;

NOTERA: Jag ringde objektet pSidebar eftersom det här är en delvis vy, inte en fullständig vy. Detta är min preferens att skilja mellan de två, men gör saker tydligare.

Skönheten att använda detta tillvägagångssätt är - vi kan använda samma metodnamn som vi använde i objektet Om och vi kommer inte ha några konflikter. Detta beror på att dessa metoder är bundna till objektets prototyp i sig, inte den globala namnrymden. Detta förenklar vår kod och möjliggör ett slags "templerande" för framtida skript.


Instantiate endast som behövs

När du har skapat dina objekt är det enkelt att ringa dem. Du behöver inte längre bero på din ram för att avfyra händelser när ditt dokument är laddat eller klart. Nu kan du enkelt ordna ditt objekt och dess händelser kommer att bindas och utföras efter behov. Så, låt oss instansera vår Handla om objekt:

Inuti din synpunkt där du skulle kalla dina syn på specifika skript (beroende på ditt språk), ring bara en ny instans av ditt objekt och inkludera filen enligt följande:

  

Som du kan se passerade jag i sidtiteln för vyn (vilket kan vara något argument för något behov - jämna Modelldata. Detta ger dig ett utmärkt sammanhang över din modelldata och gör att du enkelt kan manipulera den data i JavaScript.

Precis som din Handla om Objekt, som kallar dina partiella synpunkter är lika enkelt. Jag rekommenderar starkt att du ringer nya instanser av dina partiella JavaScript-objekt i objektets konstruktör - det här säkerställer att du bara ringer dem efter behov och att de är gemensamt på ett ställe.

 var om = funktion (pageTitle) this.pageTitle = pageTitle; // Tilldela en ny instans av Sidebar Partial View som refereras senare this.sidebar = new pSidBar (pageTitle); // Obs! Om du inte behöver referera till en partiell vy efter det faktum, // kan du helt enkelt inställa en instans av det utan att ange det inom objektets konstruktör, som så: ny pSidBar (pageTitle); // gör detsamma för partiell footer Visa this.footer = new pFooter (); // bindande händelser så snart objektet är instantiated this.bindEvents (); ;

Som du kan se, genom att referera Sidebar-objektet som en lokal egenskap hos Om-objektet, bindar vi nu den instansen, vilket är ett mycket naturligt beteende - den här instansen är nu Sidans sidans sidor.

Om du inte behöver referera till en delvis vy efter det faktum kan du helt enkelt inställa en förekomst av det utan att ange det inom objektets konstruktör, som så:

 var om = funktion (pageTitle) this.pageTitle = pageTitle; ny pSidBar (pageTitle); // bindande händelser så snart objektet är instantiated this.bindEvents (); ;

Härifrån, allt vi behöver göra är att lägga till ett annat skript i våra skript som vi kallar:

   

Varför den här tekniken är fördelaktig

När denna struktur är på plats kan vi sedan skräddarsy vårt JavaScript-objekt för att matcha vår syn och tillämpa de metoder som behövs för det objektet för att behålla omfattningen. Genom att skapa ett visnings-parallellt objekt och arbeta bort prototypens objekt, ser vi följande fördelar:

  1. Nomenklaturen gör det lättare att navigera genom kod
  2. Vi namnger naturligtvis våra föremål, minskar behovet av långa metodenamn och för mycket användning av anonym nedläggning.
  3. Lite eller ingen konflikt i annan kod eftersom våra metoder ligger på prototypen av objektet, inte på global nivå
  4. När vi instansierar våra partiella vyer inom vår View-konstruktör och tilldelar dem till en lokal variabelreferens skapar vi effektivt en lokalt bunden kopia av den delbildsobjektets objekt.
  5. Vi har en fast definition av sammanhang och kan använda sökordet "detta" utan att oroa sig.
  6. Felsökningen blir tydlig eftersom alla metoder som visas i stapeln är bundna på ett ställe.

Slutsats

Eftersom MVC-designmönstret fortsätter att bli mer populärt i designvärlden, kommer utvecklingen av JavaScript-objekt som följer DOM Element-manipulering att förändras för att vara mer skräddarsydd mot visningsspecifik och händelsespecifik manipulation. Genom att skräddarsy våra JavaScript-objekt för att skapa en parallell med våra åsikter kan vi få ett handfullt tillståndsförhållande mellan de två - en som är symantiskt i god smak, lätt att gå igenom, enkel att underhålla och perfekt för expansion som vyn växer eller ändras, vilket skapar ett permeabelt och expanderbart förhållande mellan markup och scripting.

Genom att använda ett Objects Prototype kan vi behålla ett exakt sammanhang på vårt Viss skriptobjekt och expandera det objektet med en repetitiv utvecklingsram. Vi kan sedan replikera detta format genom våra partiella synpunkter, vilket sparar tid, hjärnkraft och risk för fel och oväntat beteende.