Bygg et bildegalleri med Knockout

Forfatter: Lewis Jackson
Opprettelsesdato: 6 Kan 2021
Oppdater Dato: 14 Kan 2024
Anonim
TITAN CLOSE #3 cartoon for kids game Shadow Fight 2 shadow fight videos for kids from FGTV
Video: TITAN CLOSE #3 cartoon for kids game Shadow Fight 2 shadow fight videos for kids from FGTV

Innhold

Denne artikkelen dukket først opp i nummer 228 av .net magazine - verdens mest solgte magasin for webdesignere og utviklere.

Hvis du jobber med et ganske enkelt innholdsbasert nettsted, trenger ikke JavaScript å bli for komplisert. kanskje en lysbokseffekt for et bildegalleri og en eller annen formvalidering. Men så snart en rimelig mengde data eller behovet for å holde oversikt over UI-tilstanden i applikasjonen din blir lagt til blandingen, kan det begynne å forårsake litt av et problem.

For grensesnitt der brukeren kan bla gjennom data, endre utseendet eller posisjonen til komponentene på siden eller gjøre valg eller filtre som må vedvare, og prøve å stole på DOM-inspeksjon for å forstå hvor ting er, vil sannsynligvis ende i frustrasjon. Kanskje en bedre måte å nærme seg ting på er å ha en ren atskillelse av presentasjon og logikk, og det er her rammer som Knockout kommer inn. Du kan allerede bruke hendelsesbehandlerbindinger i jQuery eller andre JavaScript-biblioteker for å koble brukerhandlinger med deler av en side , men med Knockout kan vi gå et skritt videre og bruke JavaScript til å fylle ut grensesnittet automatisk - så når data eller tilstand endres, gjør også brukergrensesnittet.

I rik UI-utvikling kan dette i stor grad forenkle prosessen med å laste inn og oppdatere data. Det er også mer robust og testbart, så om du jobber alene eller i team er det en fin måte å gjøre livet enklere for alle.


Hva er knockout?

Knockout er en JavaScript-implementering av Model-View-View Model-mønsteret, en måte å definere data i et modellobjekt og deretter binde DOM-elementer eller maler til disse dataene. De tre delene av mønsteret er:

  • Modellen Dine data: Dette vil vanligvis bli JSON lastet via Ajax, men det er mange andre måter å få data inn i appen din, for eksempel spørring til en eksisterende DOM.
  • Utsikten HTML-en din, med ethvert element du vil fylle ut eller manipulere, gitt en data-bind Egenskap. Dette bruker HTML5-tilpassingen data-* attributt-syntaks, slik at den overfører validering, men kan også tolkes i HTML4- og XHTML-dokumenter.
  • Visningsmodellen JavaScript-objektforekomsten som forbinder alt sammen. Dette er gjenbrukbare funksjoner, slik at du kan ha flere forekomster av en visningsmodell på en side, eller hekke en barnemodell i en forelder.

Hver gang visningsmodellen endres, enten gjennom en datainnlasting eller brukerhandling, oppdateres de aktuelle databundne DOM-elementene automatisk slik at brukergrensesnittet alltid er synkronisert med visningsmodellen. Bindinger kan også være toveis, så en verdi som binder et skjemaelement vil oppdatere JavaScript-modellobjektet på brukerinngang, klar til å bli lagret tilbake på serveren.


Dokumentasjonen og interaktive opplæringene på Knockout-siden er suveren, så i stedet for å gjenta dem anbefaler jeg at du tar en titt og jobber gjennom dem for å få en følelse av hva den kan gjøre. Det er sannsynligvis verdt å nevne at bruken av data-bind attributt for mal er ikke til alles smak, og hvis du ikke er forsiktig, kan det føre til at en uønsket mengde JavaScript forurenser din fine, rene HTML. Men det er måter å håndtere dette på, og det er også mulig å legge til attributtene programmatisk når du initialiserer visningsmodellen.

Bruker den

Et enkelt eksempel på å bruke en visningsmodell for å spore og oppdatere UI-tilstand er et bildegalleri. Vi har et sett med bilder og bildetekster å vise: dette er dataene våre. Det er også behov for å angi hvilket bilde som er valgt, sammen med andre parametere, for eksempel om miniatyrområdet skal side til venstre og høyre, og om vi er i begynnelsen eller slutten av personsøkingen, og dette er UI-tilstanden. Det vil være et ganske bart eksempel, men jeg vil nevne hvor det lett kan utvides.

Det er selvfølgelig utallige eksempler på denne typen komponenter allerede der, men de fleste vil komme med sin egen ide om hvordan markeringen din skal legges ut - og å grave i den medfølgende CSS og begynne å gjøre endringer kan være en jobb. Og det er før du oppdager at plugin-modulen også gjør 10 ting du ikke trenger, noe som gir større og større kompleksitet. Sikkert en mye bedre måte er å starte med HTML og layout som du vil, og legge til funksjonalitet derfra.


Nøkkelprinsippet du må huske når du utvikler med en visningsmodell, er at det ikke har eller trenger kunnskap om hvordan DOM er strukturert eller lagt ut. UI-oppdateringer håndteres gjennom databindinger i HTML; hvis disse er til stede vil appen fungere uavhengig av hvordan den ser ut. Du kan binde så mange elementer du vil til den samme delen av visningsmodellen, og hvis det ikke lages en binding, er det ingen uheldige effekter, så du kan gjenbruke den samme logikken i mange forskjellige situasjoner.

Visningsmodellen arbeider utelukkende med data, og denne løse koblingen betyr at det er veldig enkelt å lage logiske, testbare komponenter du kan passe sammen uansett hvordan du vil. Knockout er kompatibel ned til IE6 og er ikke avhengig av noe annet JavaScript-bibliotek, så jeg har holdt demo-rammeverket agnostisk der det er mulig. Jeg bruker jQuery til å initialisere siden og vise modellen, men det er ingen grunn til at du ikke kunne erstatte dette med ditt valgte rammeverk - eller ren JavaScript.

Starter

La oss gjennomgå de tre hoveddelene som utgjør demoen. Først er dataene, eller modellen, som i dette tilfellet kommer fra en liste over lenker til bilder i et HTML-dokument.

Herfra kan vi bruke et DOM-spørsmål til å trekke ut nettadressen til hvert bilde og tilhørende billedtekst og levere dem til visningsmodellen ved hjelp av en initialisering funksjon. Vi replikerer disse dataene i en ny HTML-struktur, så i ånden av progressiv forbedring kan vi skjule den originale markeringen ved hjelp av JavaScript under sideinnlasting. På denne måten vil den grunnleggende bildelisten fremdeles være tilgjengelig for nettlesere som ikke kan bruke det rikere brukergrensesnittet.

ul> li> a href = "img / 1.webp"> Image 1 Caption / a> / li> li> a href = "img / 2.webp"> Image 2 Caption / a> / li> li> a href = "img / 3.webp"> Bilde 3 Caption / a> / li> ... li> a href = "img / 8.webp"> Image 8 Caption / a> / li> / ul>

Hvis vi tar ordene i MVVM-mønsternavnet i orden, er visningen neste, men det vil være mer fornuftig å dekke visningsmodellen først. Dette er den delen som inneholder dataene og hvilket bilde som er valgt, og senere vil vi også ta for oss hva som skjer hvis brukeren endrer valget.

var site = site || {modeller: {}}; site.models.Gallery = funksjon () {var selv = dette; this.itemsObservables = ko.observableArray (); this.init = function (data) {ko.utils.arrayForEach (data, function (item) {self.itemsObservables.push (new site.models.GalleryItem (item));}); }} site.models.GalleryItem = function (el) {this.isSelected = ko.observable (false); this.src = el.href; this.caption = el.innerHTML;}

Vanligvis lager jeg et navneområde for koden min; det reduserer sjansene for å komme i konflikt med noe annet JavaScript på nettstedet ditt, og gir dermed friheten til å ringe vår gallerivisningsmodell galleri uten å bekymre deg for at det kan være et annet ‘galleri’ definert et annet sted. Knockout oppretter også sitt eget navneområde, ko, som brukes som en container for alle sine egne metoder - i likhet med jQuerys $.

De to funksjonene som følger dette er våre visningsmodeller, en for det samlede galleriet og en for elementene i den. Som nevnt tidligere har du fleksibiliteten til å hekke barnemodeller, så det er fornuftig å bryte ting ned i separate blokker når du har funksjonalitet du vil gjenta.

Inne i hovedvisningsmodellen er en observerbar Knockout, elementerObservables, der vi lagrer dataene for galleriet vårt - bildens nettadresser og bildetekster. Å lage det på dette i stedet for som en var gjør det til en egenskap for funksjonsobjektet, slik at når vi instantierer en kopi av visningsmodellen senere, vil denne observerbare være tilgjengelig som en offentlig metode - dette er viktig for å eksponere den for databinding . Det er også en observerbar matrise, noe som betyr at når vi skyver eller fjerner elementer til den, kan Knockout spore dette og oppdatere brukergrensesnittet deretter.

Ved å erklære ko.observableArray med et tomt funksjonsanrop lager vi det med ‘udefinert’ innhold, så vi bør lage en initialiseringsmetode for å kunne legge til data i den. Den neste metoden inne i funksjonen, dette. inne, tar seg av det.

Dette er en funksjon som tar et dataarray - i vårt tilfelle vil det være resultatet av et spørsmål på DOM - og igjen er det definert som en offentlig metode, innenfor dette, slik at vi kan kalle det utenfor utsiktsmodellen.

Funksjonens kropp bruker en Knockout-verktøymetode, ko.arrayForEach, for å gå gjennom dataarrayet og skyve hvert element videre til elementerObservables. Du kan også bruke $. hver i jQuery eller _.Hver i Underscore - eller hvilken som helst annen metode du liker. Selvfølgelig når vi først er inne i dette arrayForEach tilbakeringing den har sin egen dette omfang, så i visningsmodellen har vi laget et variabelt selv for å kunne overføre referansen.

ko.utils.arrayForEach (data, function (item) {self.itemsObservables.push (new site.models.GalleryItem (item));});

I stedet for bare å skyve inn selve varen, som kommer til å være et DOM-element, lager vi en forekomst av den andre visningsmodellen, GalleriProdukt, som vil inneholde egenskapene og observerbare objektene i galleriet. Dette viser fordelen med å dele visningsmodellen vår i mindre blokker, ettersom vi kan instantiere denne barnevisningsmodellen så mange ganger vi vil.

site.models.GalleryItem = function (el) {this.isSelected = ko.observable (false); this.src = el.href; this.caption = el.innerHTML;}

Først lager vi en enkelt Knockout som kan observeres er valgt som, som det kan være åpenbart, er om denne varen er valgt eller ikke. I stedet for å gjøre det 'udefinert' med et tomt funksjonsanrop, vil vi standardsette det til false ved å legge inn verdien når vi lager det observerbare.

Så (og her stoler vi på at et element sendes inn, men du kan teste for andre om nødvendig) vi setter this.src til elementets href attributt og this.caption til dens innerHTML. Dette er enkle variabler, i stedet for observerbare, fordi vi ikke forventer at de skal endres og derfor ikke trenger overhead for å holde dem i Knockouts observerbare kjede. Og grunnen til at vi i det hele tatt gjør dette er at vi trekker ut dataene fra elementet og lagrer det i et abstrakt objekt, slik at vi kan bruke dem igjen slik vi vil.

På grunnleggende nivå er dette alt vi trenger i våre visningsmodeller for å lage et enkelt galleri. La oss nå se på HTML-malen for brukergrensesnittet, eller View, hvor vi vil databinde dens observerbare data:

div data-bind = "foreach: itemsObservables"> div> img width = "800" height = "533" data-bind = "attr: {'src': src, 'alt': caption}" /> / div> / div>

Du kan se at vi har satt opp et containerelement, en div med klassen galleri, og innenfor dette er en mal, div.item. Tidligere versjoner av Knockout krevde at du integrerte disse malene i skriptelementer, noe som fra ren HTML ikke var veldig tilfredsstillende, men i den nåværende 2.0-versjonen er dette ikke lenger nødvendig. Hvis du ønsker det, kan du til og med fjerne beholderelementer ved å bruke kontrollflytbindinger i spesialformaterte HTML-kommentarer, men vi vil ikke dekke det her.

På containeren er en data-bind attributt med verdien foreach: itemsObservables, som forteller Knockout å gå gjennom den observerbare matrisen og bruke malen på alle elementene som er inne i den. Elementene er forekomster av GalleriProdukt visningsmodell vi opprettet i init-funksjonen, slik at dataene som bindes på bildeelementet i malen kan få tilgang til src og bildetekst verdier inne i hver og angi elementattributtene deretter.

Siden den observerbare matrisen er tom før vi kaller i det metode, på det tidspunktet vil det ikke være noe div.item elementer i DOM - den tomme malen lagres ganske enkelt. Hvis vi begynner å legge til eller fjerne elementer i matrisen, fører databinding til at kopier av disse malelementene blir opprettet eller ødelagt, alt automatisk.

Det siste trinnet for å gjøre alt dette arbeidet er å lage en forekomst av Galleri vis modell på sideinnlasting og fyll den ut med vårt DOM-elementarray. Jeg bruker jQuery i en klar funksjon for dette, men erstatt gjerne ditt bibliotek og valgte teknikk:

$ (function () {var viewModel = new site.models.Gallery (); viewModel.init ($ (’ul.origin a’)); ko.applyBindings (viewModel);});

Her lager vi en variabel viewModel, som er en ny kopi av Gallerivisningsmodellen, og ring deretter i det metode, og sender inn resultatet av en DOM-spørring for alle koblingene i listen over varer. Til slutt bruker vi en Knockout-metode for å bruke dataene i visningsmodellen på alle bindingene i malene våre. Som standard vil den gjelde for kropp element, men du kan sende et ekstra argument målrettet hvor som helst på siden DOM for å begrense omfanget av bindingene, for eksempel hvis du vil ha flere uavhengige visningsmodeller på en side. Når dette er gjort, vil eventuelle endringer i visningsmodellen umiddelbart reflekteres i brukergrensesnittet, og omvendt.

Går videre

På dette tidspunktet har du et fungerende MVVM-program, men å se det i en nettleser vil markere at det ikke er veldig gallerilignende, fordi alt malen gjør er å gå gjennom elementene og vise bildene i rekkefølge. Vi trenger fremdeles en måte for brukeren å kunne se hvilket bilde i listen som er valgt og endre valget, og, viktigst, å bare vise ett hovedbilde om gangen!

For å oppnå den første delen av dette, bruker vi prinsippet om at de samme dataene kan bindes i DOM flere ganger, og setter opp en ny mal for en miniatyrrems:

div> ul data-bind = "foreach: itemsObservables"> li data-bind = "css: {'selected': isSelected}, klikk: $ parent.select"> img data-bind = "attr: {'src': src} "width =" 140 "/> span data-bind =" text: caption "> / span> / li> / ul> / div>

Vi oppretter dette ved å bruke samme forutgående Knockout-binding for å vise så mange listeelementer som det er elementer i den observerbare matrisen. Vi viser også det samme bildet src og bildetekster igjen, men i et annet markeringsmønster som viser fleksibiliteten til visningsmodellen. (Jeg bruker en klemt versjon av hovedbildet som miniatyrbilde for å gjøre det enkelt, men jeg forventer at et produksjonssted har miniatyrbilder av riktig størrelse.)

Den første bindingen på miniatyrbildelisten er css: {’Valgt’: isSelected}, som brukes til å bruke en CSS-klasse betinget - den vises bare på elementet hvis er valgt er sant, og angi det valgte elementet. Da vi opprettet GalleriProdukt visningsmodell vi gjorde dette som synlig falsk som standard, så foreløpig vil ikke klassen bli brukt. De css binding har et litt kontraintuitivt navn - det handler om klasser - men hvis du vil binde individuelle CSS-egenskaper, kan du også bruke stil bindende.

For å gjøre dette nyttig er det også et nytt konsept på listen; en binding til $ foreldre. velg på klikkhendelsen. Hvis du bruker Knockout for håndtering av hendelser, vil det ha forrang for standard DOM-hendelse, og også alle andre hendelseslyttere som kan være på dette elementet, men du kan gi kontrollen tilbake til dem senere hvis du trenger det ved å returnere true fra funksjonen vi er i ferd med å lage.

De $ foreldre prefikset til funksjonsoppgaven er der fordi vi i varemalen er i sammenheng med GalleriProdukt visningsmodell, og ved å bruke denne kan vi få tilgang til den foreldre visningsmodell, forekomsten av Galleri, og ring en funksjon å velge - som vi vil definere der. Det kan gå i GalleriProdukt se på modellen og bli ringt direkte (bruker data-bind = "click: select"), men å gjøre det vil bety at du oppretter en kopi av det med hvert element, og det er en ytterligere fordel å sette det et nivå opp også.

this.select = funksjon (data, e) {self.setSelected (newSelection); e.preventDefault ();} this.setSelected = function (newSelection) {ko.utils.arrayForEach (self.itemsObservables (), function (item) {item.isSelected (item == newSelection);});}

Egentlig er det to nye funksjoner her - å velge, som håndterer klikkhendelsen og deretter ringer settVelgt, som faktisk gjør valget. Det er ikke viktig å dele ting opp på denne måten, men ved å lage et eget settVelgt metoden kan vi teste den uavhengig uten å måtte simulere en DOM-hendelse.

Knockouts hendelsesbindinger gir to standardargumenter. Den første, data, er et øyeblikksbilde av hva mål element er bundet til; i dette tilfellet den relevante forekomsten av GalleriProdukt vis modell. Den andre, e, er den opprinnelige DOM-hendelsen. Vår funksjon kaller settVelgt med dette og forhindrer standardhandling. Da vi klikket på et listeelement i eksemplet vårt, er det ingen standardhandling, så det er egentlig ikke nødvendig, men hvis vi endrer malen for å bruke en lenke, vil den ikke fange oss ut.

Vi kunne rett og slett stille er valgt på det nye utvalget til ekte, som vil oppdatere brukergrensesnittet umiddelbart - men ethvert tidligere valg vil fortsatt være aktivt, og hvis vi vil begrense brukergrensesnittet til å vise ett hovedbilde av gangen og også ha en indikator i miniatyrremsen, vil dette være et problem.

For å forhindre dette, løper vi gjennom alle forekomster av GalleriProdukt i gjenstander Observerbar og sammenlign dem med det nye utvalget. Resultatet av denne sammenligningen er en boolsk - falsk eller sann - slik at vi kan tildele den rett til er valgt ved å kalle det observerbare med sammenligningen som argument. På denne måten kan bare ett valg gjøres om gangen, og varen som har er valgt satt til ekte vil nå få CSS-klassen valgt anvendt. Det er også her fordelen med å sette valglogikken i hovedsak Galleri visningsmodell blir tydelig, for fra dette nivået kan vi enkelt gå inn i noen av dens egne egenskaper - inkludert alle elementene i elementerObservables.

Den endelige bruken for er valgt er for å angi synligheten til hovedbildene.

div data-bind = "foreach: itemsObservables"> div data-bind = "visible: isSelected"> ... / div> / div>

Vi kan gjøre dette ved å legge til en synlig bindende til er valgt div.item. Dette fungerer ved å direkte manipulere stilen til elementet, så ethvert element der er valgt er falsk vil CSS-visningsregelen være satt til ingen, og når visningsmodellen endres, vil også elementene bli synlige.

Igjen, hvis vi ser i nettleseren, er ting ikke helt det vi forventer av et galleri. Normalt vil det første bildet i settet være valgt som standard, men som det ser ut, initialiserer vi alle elementene som skal ha er valgt satt til falsk, så ingen store bilder er synlige før brukeren velger et. For å komme rundt dette, la oss sette i hovedvisningsmodellen init-metoden er valgt på den første varen til ekte slik at den vises.

this.init = funksjon (data) {var selv = dette; ... this.itemsObservables () [0] .isSelected (true);}

I tillegg til å bruke Knockouts interne metoder (som f.eks trykk, som er sin egen i stedet for det rene JavaScript trykk) på elementerObservables array, kan vi også kalle det med () og få tilgang til alle elementene akkurat som vi ville gjort med en vanlig serie. Vi tilordner verdier til vanlige observerbare ved å kalle dem med verdien som argument, så den nye linjen i i det funksjonen nå setter er valgt i det første elementet i den observerbare matrisen til ekte.

Å få det til å passe

Nå har vi et minimalt, men funksjonelt bildegalleri. Bare ett bilde fra et sett vises samtidig, og det vises en miniatyrvisning som brukeren kan klikke på for å velge hvilken som skal vises.

Du vil imidlertid merke at med hovedbildene satt til 800px bredt, miniatyrbildestripen overløper den bredden - eller kan til og med vikles avhengig av størrelsen på nettleseren. Det ville være bedre om vi kunne begrense stripens bredde til bildestørrelsen, og la den bla til venstre eller høyre, avhengig av hvor valget er. Selvfølgelig, den 800px er en vilkårlig figur for denne demoen. Det kan være hvilken som helst størrelse, eller til og med responsiv, men å håndtere denne typen situasjoner er der Knockout virkelig kommer til sin rett.

Det er behov for en haug med nye observerbare ting for å legge til denne oppførselen i brukergrensesnittet, så vi lager en helt ny visningsmodell, ScrollableArea, for å lagre og spore dem - og hekke dette innenfor vår hovedvisningsmodell når vi definerer det.

site.models.Gallery = funksjon () {var selv = dette; this.itemsObservables = ko.observableArray (); this.measureContent = null; this.scrollable = new site.models.ScrollableArea (); ...}

Det er en annen ny eiendom her å nevne, measureContent. Du vil se at den er satt til null og i utgangspunktet er en plassholder for en funksjon vi vil definere i vår dokumentklare kode, slik at vi kan dra nytte av noen jQuery-funksjoner uten å få den bundet i vår rammeagnostiske visningsmodell. Alt annet som har med vår utvidede funksjonalitet å gjøre, kommer til ScrollableArea vis modell.

site.models.ScrollableArea = function () {var self = this; this.scrollThreshold = ko.observable (0); this.contentSize = ko.observable (0); this.scrollValue = ko.observable (0); this.scrollClickStep = ko.observable (400); this.isScrollable = ko.computed (function () {return self.contentSize ()> self.scrollThreshold ();});}

Den første biten av observerbare her holder rede på UI-tilstanden. blaTerskel er den totale bredden på bildegalleriet. I praksis vil dette være 800 men dette er en generell visningsmodell, så vi initialiserer den til 0; den virkelige størrelsen kan sendes inn i løpet av dokument klar-funksjon. contentSize er igjen initialisert til 0, og dette vil være en måling av den totale bredden på alle miniatyrelementene. Senere sammenligner vi disse verdiene for å se om miniatyrområdet skal rulle eller ikke.

Neste er scrollValue, dette er en oversikt over hvor den 'venstre' posisjonen til miniatyrremsen skal være og igjen som standard 0. Til slutt, scrollClickStep er en innstilling for hvor mye miniatyrstripen skal flyttes av når vi går til venstre eller høyre, og for vår demo er den som standard 400 (piksler).

Etter dette går vi videre til de smarte tingene, hvor kraften til Knockout virkelig blir tydelig. Så langt har vi håndtert ko.observable og ko.observableArray, men det er en tredje type observerbar, ko. beregnet, som kan se et hvilket som helst antall andre observerbare og vil returnere en beregnet verdi basert på dem når noen av dem endres. Disse kan enten være skrivebeskyttet beregning eller toveis lese / skrive-funksjoner.

Snarere enn å skape er rullbar med en enkel verdi, kaller vi det i stedet for med en funksjon som i dette tilfellet returnerer en sammenligning av to av våre tidligere observerbare, contentSize og blaTerskel, for å finne ut om den generelle bredden på miniatyrremsen er større enn plassen vi har tilgjengelig for å vise den i. Ved initialiseringstid er begge disse verdiene 0, så det vil være falsk - ikke rullbar - men så snart vi måler DOM og legger noen reelle verdier der, vil den automatisk beregne på nytt og alt i malen som er bundet til denne beregnede observerbare vil svare. Den praktiske måten å gjøre dette på er å utvide dokumentklar-funksjonen vi allerede bruker for å sette opp hovedvisningsmodellforekomsten:

$ (function () {var viewModel = new site.models.Gallery (); viewModel.init ($ ('ul.origin a')); ko.applyBindings (viewModel, $ ('body'). get (0) ); var c = $ ('div.controller'); viewModel.measureContent = function () {return c.find ('li'). width () * c.find ('li'). length;} viewModel .scrollable.contentSize (viewModel.measureContent ()); viewModel.scrollable.scrollThreshold (c.width ());});

Nå har vi lagt til en variabel c, som cacher et DOM-søk for elementet som inneholder listen over miniatyrbilder. Funksjonen viewModel.measureContent (husk at vi opprettet dette som en nullfunksjon på Galleri se modell tidligere) er nå definert som å bare returnere pikselbredden til det første listeelementet i kontrolleren ganget med antall elementer for å gi stripens totale størrelse. Det er risikabelt å stole på at alle elementene har samme bredde, men for denne demoen vil det gjøre.

Denne funksjonen brukes til å stille inn verdien på det observerbare rullbar. blaTerskel. Merk at vi kan sette verdier direkte inn i et nestet nivå av visningsmodellen, fordi forekomsten av ScrollableArea ble definert som en offentlig metode og dens observerbare er også offentlige. Vi setter også rullbar. blaTerskel til bredden på selve containeren. Det er viktig å sette disse verdiene etter at visningsmodellbindingen er brukt på DOM, for å sikre at vi måler det fullstendige gjengitte resultatet i stedet for tomme maler.

Endring av verdien på en av disse observerbare faktorene fører til er rullbar som kan observeres for å bli beregnet på nytt, og hvis innholdsstørrelsen nå er bredere enn den plassen vi har tilgjengelig, blir den sann.

div> ul data-bind = "foreach: itemsObservables, style: {'width': scrollable.contentSize () + 'px'}"> ... / ul> button data-bind = "synlig: scrollable.isScrollable, enable : scrollable.canScrollLeft, klikk: scrollable.scrollContent "data-direction =" left ">« / button> button data-bind = "visible: scrollable.isScrollable, enable: scrollable.canScrollRight, click: scrollable.scrollContent" data-direction = "høyre"> »/ knapp> / div>

Å gjøre bruk av er rullbar i brukergrensesnittet endrer vi også malen for miniatyrremser. Du vil se at det er en stil bindende på listen for å stille inn bredden til vår forrige beregning; Dette er for å sikre at det hele er lagt ut på en linje selv om container element vil bli begrenset til en bredde med overløp: skjult anvendt. Resten av varemalen er den samme som før, men vi har også lagt til to knapp elementer, som begge har en synlig bindende til er rullbar. Du kan sannsynligvis finne ut hvilken effekt dette har; knappene vil bli satt til å vises: ingen til er Scrollable blir sanne, på hvilket tidspunkt de automatisk kommer til syne.

Det er også en muliggjøre bindende på disse knappene. Jeg vil ikke gå inn i detaljene til de beregnede observasjonene som beregner om de er sanne eller falske, men de inneholder logikken som sammenligner den nåværende rulleposisjonen med potensielle maksimums- og minimumsverdier og forhindrer brukeren å bla til venstre i venstre ende av miniatyrremsen, og omvendt.

Endelig har knappene også en klikk binding til en funksjon scrollContent, som legger til eller trekker fra rulletrinnsbeløpet til gjeldende rulleverdi avhengig av retningen du klikker på. Dette setter til slutt en annen beregnet observerbar på ScrollableArea vis modell, calculatedScrollValue.

this.calculatedScrollValue = ko.computed ({les: funksjon () {retur (self.isScrollable ())? self.scrollValue (): 0;}, skriv: funksjon (verdi) {self.scrollValue (verdi);}} );

Her er et eksempel på en toveis beregnet observerbar, som inneholder tilbakekallingsfunksjoner til både lese- og skriveverdier. I lese funksjon vil den reagere på endringer i er rullbar, men hvis vi kaller det med en verdi i argumentet så skrive funksjon utløses for å stille scrollValue, som vi kan bruke i en stil bindes på malen for å plassere miniatyrremsen.

Innpakning

Ganske mange konsepter har blitt introdusert raskt i denne demoen, og du vil bli tilgitt hvis noen av dem har gjort mer for å forvirre enn å belyse. Men forhåpentligvis har du sett noen av fordelene ved å bruke et MVVM-mønster og er opptatt av å lese videre om det. Som vi sa i starten, er dokumentasjonen og veiledningen på Knockout-siden fantastisk og vel verdt å jobbe gjennom.

Det er også en hel del mer dybde, inkludert tilpassede bindinger som kan kobles direkte til jQuery eller andre biblioteks effekter. Så snarere enn en enkel synlig bindende kan du definere din egen fadeVisible å få elementer til å vises og forsvinne med litt mer stil enn bare å poppe inn eller ut eller se.

Den viktigste tingen å huske er at gjennom alt beskrevet har vi hatt som mål å opprettholde en ren skille mellom brukergrensesnitt og logikk. Så vi kunne helt erstatte utsikten, så lenge bindingen ble overført, og det hele ville fortsatt fungere.

Det er selvfølgelig utallige, betydelig mer funksjonsrike, galleri-plugin-moduler der ute for JavaScript-rammeverk du vil nevne. Men dette er bare utgangspunktet for vårt Knockout-drevne galleri, og for meg er fordelen med å gjøre det på denne måten at du ender opp med en kompakt, men likevel utvidbar kontroller i form av visningsmodellen, som kan brukes på ethvert brukergrensesnitt uten å måtte bekymre deg for hvor fint den vil spille med den eksisterende siden din.

Dette er en revidert, utvidet versjon av en artikkel som først ble publisert på 12devsofxmas.co.uk

Oppdag 101 CSS- og JavaScript-opplæringsprogrammer for å styrke ferdighetene dine på Creative Bloq.

Vi Anbefaler Deg
Hva skjer når tatoveringsdesign møter illustrasjon
Lese

Hva skjer når tatoveringsdesign møter illustrasjon

Rundt 2010 hang jeg med en gruppe tatovering arti ter og di kuterte den økende populariteten til tatovering. Vi trodde det var en bølge om nart kulle kra je, og bare etterlot diehard. Hvor f...
5 designbransjetrender som studenter trenger å vite om
Lese

5 designbransjetrender som studenter trenger å vite om

Noen ganger har noen nyutdannede klaget til o at de ignkur et dere var litt etter gangen. Men hvi det var tilfelle, er det ikke helt overra kende. Fra et prakti k yn punkt tar det litt tid å ette...
Hvordan kombinere Painters akvarellsett
Lese

Hvordan kombinere Painters akvarellsett

Corel Painter tilbyr en bankett med akvarellverktøy. Den kan kilte med digitale, ekte og akvarellverktøy kategorier, hver med en rekke bør ter. Men kategoriene Ekte og Akvarell krever e...