Knockout Observables

Abbiamo visto come le proprietà osservabili consentono a Knockout.js di aggiornare automaticamente gli elementi HTML al variare dei dati sottostanti, ma questo è solo l'inizio della loro utilità. Knockout.js ha anche altri due modi di esporre le proprietà ViewModel: osservabili calcolati e matrici osservabili. Insieme, questi dischi aprono un nuovo mondo di possibilità per interfacce utente basate sui dati.

Osservabili calcolati ti consente di creare proprietà generate dinamicamente. Ciò significa che puoi combinare diversi osservabili normali in una singola proprietà e Knockout.js manterrà la visualizzazione aggiornata ogni volta che uno qualsiasi dei valori sottostanti cambia.

Figura 12: Un osservabile calcolato dipende da due osservabili normali

Matrici osservabili combinare la potenza delle osservabili di Knockout.js con gli array JavaScript nativi. Come gli array nativi, contengono elenchi di elementi che puoi manipolare. Ma dal momento che sono osservabili, Knockout.js aggiorna automaticamente tutti gli elementi HTML associati ogni volta che gli articoli vengono aggiunti o rimossi.

Figura 13: Un array osservabile contenente altri ViewModels

La possibilità di combinare gli osservabili, insieme alla possibilità di lavorare con elenchi di elementi, fornisce tutte le strutture di dati necessarie in un ViewModel. Questa lezione introduce entrambi gli argomenti con una semplice interfaccia per il carrello degli acquisti.


Osservabili calcolati

Innanzitutto, inizieremo con un semplice osservabile calcolato. Sotto il nome di battesimo e cognome osservabili in PersonViewModel, crea l'osservabile calcolato fullName:

 this.fullName = ko.computed (function () return this.firstName () + "" + this.lastName ();, this);

Definisce una funzione anonima che restituisce il nome completo della persona ogni volta PersonViewModel.fullName è accessibile. Generazione dinamica del nome completo dai componenti esistenti (nome di battesimo e lastName) ci impedisce di archiviare dati ridondanti, ma questa è solo metà della battaglia. Dobbiamo passare questa funzione a ko.computed () per creare un osservabile calcolato. Ciò indica a Knockout.js che è necessario aggiornare qualsiasi elemento HTML associato alla proprietà fullName ogni volta che si modifica firstNome o lastName.

Assicuriamoci che i nostri lavori osservabili calcolati vincolino la linea "Carrello di John's" a nome e cognome invece di firstName:

 

Carrello della spesa

Ora la tua pagina dovrebbe leggere "Carrello della spesa di John Smith". Successivamente, assicurati che Knockout.js mantenga questo elemento HTML sincronizzato quando cambiamo una delle proprietà sottostanti. Dopo aver vincolato un'istanza di PersonViewModel, prova a cambiare la proprietà firstName:

 var vm = new PersonViewModel (); ko.applyBindings (vm); vm.firstName ( "Maria");

Questo dovrebbe cambiare la linea in "Carrello della Mary Smith". Ancora una volta, ricorda che la lettura o l'impostazione di osservabili dovrebbe essere eseguita con chiamate di funzione, non con l'assegnazione (=operatore).

Gli osservabili calcolati offrono molti degli stessi vantaggi della sincronizzazione automatica della vista di Knockout.js. Invece di dover tenere traccia di quali proprietà si basano su altre parti del ViewModel, le osservabili calcolate consentono di creare l'applicazione attorno alle proprietà atomiche e delegare il rilevamento delle dipendenze a Knockout.js.


Matrici osservabili

Gli array osservabili consentono a Knockout.js di tenere traccia degli elenchi di elementi. Esploreremo questo creando una pagina di visualizzazione del carrello degli acquisti per il nostro utente. Per prima cosa, dobbiamo creare un oggetto personalizzato per rappresentare i prodotti. Nella parte superiore del nostro script, prima di definire PersonViewModel, aggiungi la seguente definizione dell'oggetto:

 funzione Product (nome, prezzo) this.name = ko.observable (name); this.price = ko.observable (price); 

Questo è solo un semplice oggetto dati per memorizzare alcune proprietà. Si noti che è possibile assegnare a più oggetti proprietà osservabili e Knockout.js gestirà tutte le interdipendenze da solo. In altre parole, è possibile creare relazioni tra multiplo ViewModels in una singola applicazione.

Successivamente, creeremo alcune istanze del nostro nuovo Prodotto classe e aggiungerli al carrello virtuale dell'utente. All'interno di PersonViewModel, definire una nuova proprietà osservabile chiamata shoppingCart:

 this.shoppingCart = ko.observableArray ([nuovo prodotto ("Beer", 10.99), nuovo prodotto ("Brats", 7.99), nuovo prodotto ("Buns", 1.49)]);

Questo è un array nativo di JavaScript contenente tre prodotti racchiusi in un array osservabile, in modo che Knockout.js possa tenere traccia quando gli articoli vengono aggiunti e rimossi. Ma, prima di iniziare a manipolare gli oggetti, aggiorniamo la nostra vista in modo da poter vedere il contenuto di carrello della spesa proprietà. Sotto il

tag, aggiungi il seguente:

 
Prodotto Prezzo

Questa è una tipica tabella HTML 5 contenente una colonna per i nomi dei prodotti e un'altra per i prezzi dei prodotti. Questo esempio introduce anche un nuovo collegamento chiamato per ciascuno. Quando Knockout.js incontra foreach: shoppingCart, scorre attraverso ogni oggetto in ViewModel carrello della spesa proprietà. Qualsiasi markup all'interno del ciclo viene valutato nel contesto di ciascun elemento, quindi il testo: nome in realtà si riferisce a shoppingCart [i] .name. Il risultato è una tabella di articoli accanto ai loro prezzi:

Figura 14: Screenshot dell'elenco dei prodotti sottoposti a rendering

I dettagli del per ciascuno vincolanti non rientrano nell'ambito di questa lezione. La lezione successiva fornisce una discussione approfondita su foreach e introduce anche gli altri binding control-flow di Knockout.js. Per ora, torniamo agli array osservabili.

Aggiungere articoli

L'intero scopo dell'utilizzo di array osservabili è consentire a Knockout.js di sincronizzare la vista ogni volta che aggiungiamo o rimuoviamo elementi. Ad esempio, possiamo definire un metodo sul nostro ViewModel che aggiunge un nuovo elemento, in questo modo:

 this.addProduct = function () this.shoppingCart.push (new Product ("More Beer", 10.99)); ;

Quindi, possiamo creare un pulsante per chiamare il metodo in modo da poter aggiungere elementi in fase di esecuzione e vedere Knockout.js mantenere aggiornato l'elenco. Accanto al pulsante checkout nel codice della vista, aggiungi quanto segue:

 

Quando si fa clic su questo pulsante, ViewModel addProduct () il metodo è eseguito. E da allora carrello della spesa è un array osservabile, Knockout.js ne inserisce un altro elemento per visualizzare il nuovo elemento. Lasciando Knockout.js tieni traccia degli elementi della lista come questo è molto meno incline agli errori di cercare di aggiornare manualmente il file

ogni volta che cambiamo l'array sottostante.

Vale anche la pena sottolineare che Knockout.js fa sempre il minimo quantità di modifiche necessarie per sincronizzare l'interfaccia utente. Invece di rigenerare l'intero elenco ogni volta che un elemento viene aggiunto o rimosso, Knockout.js tiene traccia delle parti del DOM interessate e degli aggiornamenti solo quegli elementi. Questa ottimizzazione integrata consente di adattare la tua applicazione a centinaia o persino migliaia di articoli senza sacrificare la reattività.

Eliminazione di articoli

Allo stesso modo, Knockout.js può anche eliminare elementi da un array osservabile tramite rimuovere() metodo. All'interno della definizione di PersonViewModel, aggiungi un altro metodo per rimuovere gli elementi:

 this.removeProduct = function (product) this.shoppingCart.remove (prodotto); ;

Quindi, aggiungi un pulsante Elimina per ciascun elemento nel

ciclo continuo:

 

Perché siamo nel per ciascuno contesto, abbiamo dovuto usare il $ radice riferimento per accedere al nostro ViewModel anziché all'elemento corrente nel loop. Se provassimo a chiamare removeProduct () senza questo riferimento, Knockout.js avrebbe tentato di chiamare il metodo sulla classe Product, che non esiste. Tutti i contesti di associazione disponibili per foreach sono trattati nella prossima lezione.

Il fatto che siamo in a per ciascuno loop fa incasinare anche il Questo riferimento in removeProduct (), quindi fare clic su Rimuovere il pulsante lancia in realtà un errore TypeError. Possiamo utilizzare un comune trucco JavaScript per risolvere questo tipo di problemi relativi all'ambito. Nella parte superiore della definizione di PersonViewModel, assegna a una nuova variabile denominata self:

 function PersonViewModel () var self = this; ... 

Quindi, usa se stesso invece di Questo nel metodo removeProduct ():

 this.removeProduct = function (product) self.shoppingCart.remove (prodotto); ;

Ora dovresti essere in grado di manipolare il nostro array osservabile con il Aggiungi birra e Rimuovere pulsanti. Nota inoltre che Knockout.js aggiunge automaticamente l'elemento corrente nel ciclo come primo parametro removeProduct ().

Distruggere oggetti

Il rimuovere() il metodo è utile per la manipolazione in tempo reale degli elenchi, ma può rivelarsi problematico quando si inizia a provare a inviare dati da ViewModel a uno script sul lato server.

Ad esempio, considerare l'attività di salvataggio del carrello acquisti in un database ogni volta che l'utente ha aggiunto o eliminato un elemento. Con rimuovere(), l'oggetto è rimosso subito, quindi tutto ciò che puoi fare è inviare al tuo server la nuova lista nella sua interezza: non è possibile determinare quali articoli sono stati aggiunti o rimossi. È necessario salvare l'intero elenco o calcolare manualmente la differenza tra la versione precedente memorizzata nel database e quella nuova inoltrata dalla richiesta AJAX.

Nessuna di queste opzioni è particolarmente efficiente, specialmente considerando che Knockout.js sa con precisione quali oggetti sono stati rimossi. Per rimediare a questa situazione, gli array osservabili includono a distruggere() metodo. Prova a cambiare PersonViewModel.removeProduct () al seguente:

 this.removeProduct = function (product) self.shoppingCart.destroy (prodotto); alert (self.shoppingCart () di lunghezza.); ;

Ora quando si fa clic sul Rimuovere pulsante, Knockout.js non lo farà rimuovere l'elemento dall'array sottostante. Questo è mostrato nel messaggio di avviso, che dovrebbe non diminuire quando si fa clic su "Rimuovi". Invece di alterare l'elenco, il distruggere() il metodo aggiunge a _distruggere proprietà al prodotto e imposta su true. È possibile visualizzare questa proprietà aggiungendo un altro messaggio di avviso:

 alert (product._destroy);

Il _distruggere proprietà consente di ordinare attraverso un elenco osservabile e di estrarre solo gli elementi che sono stati cancellati. Quindi, puoi inviare solo quegli elementi per uno script sul lato server da eliminare. Questo è un modo molto più efficiente di gestire gli elenchi quando si lavora con richieste AJAX.

Si noti che il per ciascuno loop è a conoscenza di questa convenzione e rimuove ancora gli associati

elemento dalla vista, anche se l'elemento rimane nell'array sottostante.

Altri metodi di matrice

Internamente, gli array osservabili sono come normali proprietà osservabili, tranne che sono supportati da una matrice JavaScript nativa invece che da una stringa, un numero o un oggetto. Come i normali osservabili, è possibile accedere al valore sottostante chiamando l'array osservabile senza alcuna proprietà:

 this.debugItems = function () var message = ""; var nativeArray = this.shoppingCart (); per (var i = 0; i 

La chiamata di questo metodo eseguirà il loop degli elementi della lista nativa e inoltre fornisce l'accesso ai metodi di array JavaScript nativi come Spingere(), pop(), shift (), sort (), ecc.

Tuttavia, Knockout.js definisce propria versioni di questi metodi sull'oggetto array osservabile. Ad esempio, all'inizio di questa lezione, abbiamo usato shoppingCart.push () per aggiungere un elemento invece di shoppingCart (). spingere (). Il primo chiama la versione di Knockout.js e quest'ultimo chiama push () sull'array nativo di JavaScript.

Di solito è un'idea molto migliore usare i metodi dell'array di Knockout.js invece di accedere direttamente all'array sottostante perché consente a Knockout.js di aggiornare automaticamente tutti i componenti della vista dipendente. Segue l'elenco completo dei metodi di array osservabili forniti da Knockout.js. La maggior parte di questi agisce esattamente come le controparti JavaScript native.

  • Spingere()
  • pop()
  • unshift()
  • cambio()
  • fetta()
  • rimuovere()
  • Rimuovi tutto()
  • distruggere()
  • destroyAll()
  • ordinare()
  • invertito()
  • indice di()

Sommario

In questa lezione, abbiamo visto come gli osservabili calcolati possono essere usati per combinare normali osservabili in proprietà composte che Knockout.js può tracciare. Abbiamo anche lavorato con array osservabili, che sono un modo per Knockout.js di sincronizzare gli elenchi di dati nel ViewModel con componenti HTML.

Insieme, gli osservabili atomici, calcolati e di array forniscono tutti i tipi di dati sottostanti di cui avrete bisogno per un'interfaccia utente tipica. Gli osservabili calcolati e gli array osservabili rendono Knockout.js una grande opzione per la prototipazione rapida. Ti permettono di mettere tutte le tue complesse funzionalità in un unico posto e poi lascia che Knockout.js si occupi di tutto il resto.

Ad esempio, sarebbe banale creare un osservabile calcolato che calcoli il prezzo totale di ciascun articolo nel carrello della spesa elencalo e visualizzalo in fondo alla pagina. Una volta creata questa funzionalità, puoi riutilizzarla in qualunque posto è necessario il prezzo totale (ad es. una richiesta AJAX) semplicemente accedendo a una proprietà ViewModel.

La lezione successiva introduce i binding del flusso di controllo. Il per ciascuno il binding che abbiamo usato in questa lezione è probabilmente lo strumento di flusso di controllo più comune, ma Knockout.js include anche alcuni altri binding per il controllo a grana fine sui nostri componenti di visualizzazione HTML.

Questa lezione rappresenta un capitolo da Knockout in modo succinto, un eBook gratuito dal team di Syncfusion.