Dieser Artikel wurde maschinell übersetzt.

Approfondimenti sul client

Introduzione a Knockout

John Papa

John PapaL'associazione dati è una delle caratteristiche più popolari in sviluppo di oggi, e la libreria JavaScript Knockout porta quelle caratteristiche allo sviluppo HTML e JavaScript. La semplicità della sintassi di associazione dichiarativa e una perfetta integrazione con modelli di separazione, come Model-View-ViewModel (MVVM) fanno attività comuni dell'impianto idraulico push-pull molto più semplice mentre rendendo più facile da mantenere e migliorare il codice.In questa colonna Client Insight inaugurale che tratterò gli scenari per il quale è l'ideale, Knockout spiegano come iniziare con esso e viene illustrato come utilizzare le sue caratteristiche fondamentali.Gli esempi di codice che si possono scaricare da archive.msdn.microsoft.com/mag201202Client, dimostrare come utilizzare l'associazione dichiarativa, creare diversi tipi di oggetti binding e scrivere codice JavaScript basato sui dati che segue i modelli di buona separazione ad esempio MVVM.

 Guida introduttiva

Knockout, sviluppato da Steve Sanderson, è una libreria JavaScript open source piccolo con una licenza MIT.Knockoutjs.com mantiene un elenco aggiornato dei browser che supporti ad eliminazione diretta (attualmente supporta tutti i principali browser, compresi Internet Explorer 6++, Firefox 2++, Chrome, Opera e Safari).Hai bisogno di alcuni importanti risorse per iniziare a sviluppare con eliminazione diretta.Partire da ottenere la versione più recente di Knockout (attualmente 2.0.0) da bit.ly/scmtAi fare riferimento a esso nel vostro progetto.Se si sta utilizzando Visual Studio 2010, però, mi raccomando che installare e utilizzare l'estensione NuGet Package Manager Visual Studio per scaricare ad eliminazione diretta (e tutte le altre raccolte potrebbe utilizzare) perché gestire versioni e avvisare l'utente quando un nuovo disponibile.NuGet Scarica Knockout e mettere due file JavaScript nella cartella script del vostro progetto.Il file minified è consigliato per la produzione e segue la denominazione convenzione knockout-x.y.z.js dove x.y.z è il maggiore, minore e il numero di revisione.C'è anche un file knockout-x.y.x-debug.js, che contiene il codice sorgente ad eliminazione diretta in forma leggibile.Consiglia di riferimento a questo file quando imparando ad eliminazione diretta e durante il debug.

Una volta che avete i file, aprire la pagina HTML (o file rasoio. Se stai usando ASPNET MVC), creare uno script e fare riferimento alla libreria ad eliminazione diretta:

<script src="../scripts/knockout-2.0.0.js" type="text/javascript"></script>

Nessun Bindings

Knockout è meglio spiegato esaminando prima come si sarebbe scrivere codice per spingere i dati da un oggetto di origine agli elementi HTML senza utilizzare ad eliminazione diretta (il codice sorgente di rilevante può essere trovato nella pagina di esempio 01 senza knockout.html nell'esempio di codice scaricabile). Quindi mostrerò come realizzare la stessa cosa usando Knockout. Inizierò con alcuni elementi di destinazione HTML e spingere alcuni valori da un oggetto di origine in questi elementi HTML:

<h2>Without Knockout</h2>

<span>Item number:</span><span id="guitarItemNumber"></span>

<br/>

<span>Guitar model:</span><input id="guitarModel"/>

<span>Sales price:</span><input  id="guitarSalesPrice"/>

Se si dispone di un oggetto da cui si desidera inserire dati elementi HTML standard, è possibile utilizzare jQuery:

$(document).ready(function () {

  var product = {

    itemNumber: "T314CE",

    model: "Taylor 314ce",

    salePrice: 1199.95

    };

    $("#guitarItemNumber").text(product.itemNumber);

    $("#guitarModel").val(product.model);

    $("#guitarSalesPrice").val(product.salePrice);

});

Nell'esempio di codice utilizza jQuery per individuare gli elementi HTML con gli ID corrispondenti e imposta i valori per ciascuna proprietà dell'oggetto appropriato.

Ci sono tre principali punti da notare in questo codice. In primo luogo, i valori sono spinto dall'oggetto di origine in elementi HTML, così che richiedono una riga di codice per ogni mapping dal valore di origine a un elemento di destinazione. Se ci sono state molte proprietà più (o se ci fossero matrici e oggetti grafici), il codice potrebbe facilmente ottenere ingombrante. In secondo luogo, se i valori nell'oggetto di origine cambiano, gli elementi HTML non rifletteranno che il cambiamento a meno che il codice per spingere i valori fu chiamato di nuovo. In terzo luogo, se i valori cambiano negli elementi HTML (la destinazione), le modifiche non sarà riportate nell'oggetto di origine sottostante. Naturalmente, tutto questo potrebbe essere risolto con un sacco di codice, ma cercherò di risolvere il problema tramite l'associazione dati.

L'HTML stesso potrebbe essere riscritto usando ad eliminazione diretta:

<h2>With Knockout</h2>

<span Item number</span><span data-bind="text: itemNumber"></span>

<br/>

<span>Guitar model:</span><input data-bind="value: model"/>

<span>Sales price:</span><input data-bind="value: salePrice"/>

Notare che gli attributi id sono stati sostituiti da associare attributi. Una volta che si chiama la funzione applyBindings, Knockout associa l'oggetto ("prodotto" in questo esempio) alla pagina. Questa imposta l'oggetto prodotto, il che significa che gli elementi di destinazione possono quindi identificare la proprietà di quel contesto dati a cui si desidera associare il contesto dati per la pagina:

ko.applyBindings(product);

I valori nell'oggetto di origine saranno spinto agli elementi bersaglio in questa pagina. (Tutte le funzioni di Knockout esistono all'interno di un proprio spazio dei nomi: ko). Il collegamento tra gli elementi di destinazione e l'oggetto di origine è definito dall'attributo associare. Nell'esempio precedente, Knockout vede l'attributo associare per il primo tag span è identificare che il relativo valore text deve essere associato alla proprietà NumeroElemento. Knockout poi spinge il valore della proprietà product.itemNumber per l'elemento.

Si può vedere come utilizzando Knockout potrebbe ridurre facilmente codice. Il numero di proprietà e gli elementi di aumento, il solo codice JavaScript necessario è la funzione applyBindings. Tuttavia, questo non ancora risolve tutti i problemi. In questo esempio viene ancora non aggiorna i bersagli HTML quando i cambiamenti di origine, né fa l'oggetto di origine aggiorna quando il codice HTML gli obiettivi di cambiamento. Per questo, abbiamo bisogno di osservabili.

Osservabili

Knockout aggiunge dipendenza di rilevamento attraverso osservabili, che sono oggetti che possono notificare gli ascoltatori quando sottostanti valori sono cambiati (questo è simile al concetto dell'interfaccia INotifyPropertyChanged nella tecnologia XAML). Knockout implementa la proprietà osservabili eseguendo il wrapping di proprietà dell'oggetto con una funzione personalizzata denominata osservabile. Ad esempio, anziché impostare una proprietà in un oggetto in questo modo:

var product = {

  model: "Taylor 314ce"

}

è possibile definire la proprietà di essere una proprietà osservabili utilizzando Knockout:

var product = {

  model: ko.observable("Taylor 314ce")

}

Una volta che le proprietà sono definite come osservabili, l'associazione dati veramente prende forma. Il codice JavaScript nella Figura 1 dimostra due oggetti che Knockout si lega agli elementi HTML. Il primo oggetto (data.product1) definisce le proprietà utilizzando un oggetto semplice letterale, mentre il secondo oggetto (data.product2) definisce le proprietà come osservabili ad eliminazione diretta.

Figura 1 con e senza osservabili

$(document).ready(function () {

  var data = {

    product1: {

      id: 1002,

      itemNumber: "T110",

      model: "Taylor 110",

      salePrice: 699.75

    },

    product2: {

      id: ko.observable(1001),

      itemNumber: ko.observable("T314CE"),

      model: ko.observable("Taylor 314ce"),

      salePrice: ko.observable(1199.95)

    }

  };

  ko.applyBindings(data);

});

Il codice HTML per questo esempio, mostrato in Figura 2, mostra quattro insiemi di associazioni di elemento. Il tag div prima e la seconda contengono elementi HTML associati alla proprietà non osservabili. Quando vengono modificati i valori nella prima div, notare che cambia nient'altro. I tag div terzo e quarto contengono gli elementi HTML associati alla proprietà osservabili. Si noti che quando i valori vengono modificati in terza div, gli elementi div quarto vengono aggiornati. Si può provare questa demo tramite esempio 02-observable.html.

Figura 2 associazione alle osservabile e Non osservabili

<div>

  <h2>Object Literal</h2>

  <span>Item number</span><span data-bind="text: product1.itemNumber"></span>

  <br/>

  <span>Guitar model:</span><input data-bind="value: product1.model"/>

  <span>Sales price:</span><input data-bind="value: product1.salePrice"/>

</div>

<div>

  <h2>Underlying Source Object for Object Literal</h2>

  <span>Item number</span><span data-bind="text: product1.itemNumber"></span>

  <br/>

  <span>Guitar model:</span><span data-bind="text: product1.model"></span>

  <span>Sales price:</span><span data-bind="text: product1.salePrice"></span>

</div>

<div>

  <h2>Observables</h2>

    <span>Item number</span><span data-bind="text: product2.itemNumber"></span>

  <br/>

    <span>Guitar model:</span><input data-bind="value: product2.model"/>

    <span>Sales price:</span><input data-bind="value: product2.salePrice"/>

</div>

<div>

  <h2>Underlying Source Object for Observable Object</h2>

  <span>Item number</span><span data-bind="text: product2.itemNumber"></span>

  <br/>

    <span>Guitar model:</span><span data-bind="text: product2.model"></span>

    <span>Sales price:</span><span data-bind="text: product2.salePrice"></span>

</div>

(Nota: Knockout non richiede di utilizzare le proprietà osservabili. Se si desidera elementi DOM a ricevere i valori di una volta, ma poi non essere aggiornato quando cambiano i valori nell'oggetto di origine, saranno sufficiente semplici oggetti. Tuttavia, se si desidera che l'oggetto di origine e destinazione elementi DOM a rimanere in sincronia — Associazione due vie — poi ti consigliamo di considerare l'utilizzo di proprietà osservabili.)

Binding incorporati

Gli esempi finora hanno dimostrato come associare al testo di Knockout e associazioni di valore. Knockout ha molti binding incorporati che rendono più facile per associare le proprietà dell'oggetto a elementi DOM di destinazione. Ad esempio, quando Knockout vede un'associazione di testo, imposterà la proprietà innerText (utilizzando Internet Explorer) o la proprietà equivalente in altri browser. Quando viene utilizzata l'associazione di testo, qualsiasi testo precedente verrà sovrascritta. Mentre ci sono molti binding incorporati, alcune delle più comuni per la visualizzazione può essere trovata Figura 3. La documentazione Knockout online contiene un elenco completo nel riquadro di spostamento a sinistra (bit.ly/ajRyPj).

Figura 3 comuni Knockout Bindings

Esempio Scenario
Testo: modello Associa la proprietà (modello) per il valore di testo per l'elemento di destinazione. Spesso usato per elementi di sola lettura come campate.
visibile: isInStock Associa la proprietà di valore (isInStock) per la visibilità dell'elemento di destinazione. Il valore della proprietà valuterà su true o false.
valore: prezzo Associa il valore della proprietà (prezzo) all'elemento di destinazione. Spesso utilizzato con gli elementi di input, select e textarea.
CSS: className Associa il valore della proprietà (className) all'elemento di destinazione. Spesso usato per impostare o attivare o disattivare i nomi delle classi css per elementi DOM.
controllato da: isInCart Associa il valore della proprietà (isInCart) per l'elemento di destinazione. Utilizzati per gli elementi checkbox.
fare clic su: saveData Aggiunge un gestore eventi per la funzione JavaScript associato (saveData) quando l'utente fa clic sull'elemento DOM. Funziona su qualsiasi elemento DOM, ma è spesso usato per il pulsante, di ingresso e un elementi.
attr: {src: photoUrl, alt: Nome} Lega qualsiasi attributo specificato per l'elemento DOM dell'oggetto di origine. Spesso usato quando le altre associazioni incorporate non coprono lo scenario, come ad esempio con l'attributo src di un tag img.

ObservableArrays

Ora che gli esempi precedenti ha ottenuto i piedi bagnati con Knockout, è tempo di passare ad un esempio ancora fondamentale ancora più pratico con dati gerarchici. Knockout supporta molti tipi di associazioni, inclusa l'associazione a proprietà semplici (come visto negli esempi precedenti), associazione agli array JavaScript, calcolate associazioni e associazioni personalizzate (che prenderò in esame in un prossimo articolo ad eliminazione diretta). Nell'esempio seguente viene illustrato come associare una matrice di oggetti di prodotto utilizzando Knockout per una lista (mostrato in Figura 4).

Binding to an Observable Array
Figura 4 associazione a una matrice osservabile

Quando si tratta di oggetti grafici e l'associazione dati, è utile incapsulare tutti i dati e le funzioni che della pagina richiede in un singolo oggetto. Questa viene definita spesso come un ViewModel da modello MVVM. In questo esempio, la vista è la pagina HTML e i relativi elementi DOM. Il modello è la gamma di prodotti. ViewModel Colle il modello nella vista; la colla che utilizza è ko.

La gamma di prodotti è impostata utilizzando la funzione observableArray. Questo è simile al ObservableCollection nelle tecnologie XAML. Perché la proprietà dei prodotti è un observableArray, ogni volta che un elemento viene aggiunto o rimosso dall'array, gli elementi di destinazione verranno notificati e l'elemento sarà aggiunto o rimosso dal DOM, come illustrato di seguito:

var showroomViewModel = {

  products: ko.observableArray()

};

Il showroomViewModel è l'oggetto radice che sarà dati associato agli elementi di destinazione. Esso contiene un elenco di prodotti che provengono da un servizio dati JSON. La funzione che carica l'elenco dei prodotti è la funzione showroomViewModel.load, che appare in Figura 5 insieme al resto dei JavaScript che imposta l'oggetto showroomViewModel (troverete il sorgente completo e dati di esempio per questo esempio in observableArrays.html-03). La funzione di caricamento loop attraverso i dati di prodotto campione e utilizza la funzione di prodotto per creare nuovi oggetti prodotto prima li spingendo verso il observableArray.

Figura 5 definire i dati per l'associazione

var photoPath = "/images/";

function Product () {

  this.id = ko.observable();

  this.salePrice = ko.observable();

  this.listPrice = ko.observable();

  this.rating = ko.observable();

  this.photo = ko.observable();

  this.itemNumber = ko.observable();

  this.description = ko.observable();

  this.photoUrl = ko.computed(function () {

    return photoPath + this.photo();

  }, this);

};

var showroomViewModel = {

  products: ko.observableArray()

};

showroomViewModel.load = function () {

  this.products([]); // reset

  $.each(data.Products, function (i, p) {

    showroomViewModel.products.push(new Product()

      .id(p.Id)

      .salePrice(p.SalePrice)

      .listPrice(p.ListPrice)

      .rating(p.Rating)

      .photo(p.Photo)

      .itemNumber(p.ItemNumber)

      .description(p.Description)

      );

  });

};

ko.applyBindings(showroomViewModel);

Anche se la proprietà di un prodotto sono tutte definite utilizzando osservabili, non necessariamente essere osservabile. Ad esempio, questi potrebbero essere proprietà di pianura, se sono di sola lettura e se — quando assume la fonte — sia il bersaglio non è previsto per essere aggiornati o l'intero contenitore dovrebbe essere aggiornati. Tuttavia, se le proprietà devono essere aggiornati quando la fonte cambia o è edito nel DOM, poi osservabile è la scelta giusta.

La funzione prodotto definisce tutte le sue proprietà osservabili ad eliminazione diretta (tranne photoUrl). Quando Knockout associa i dati, la proprietà di matrice prodotti accessibili, che lo rende facile da usare funzioni standard, come lunghezza per mostrare quanti elementi sono attualmente associato ai dati:

<span data-bind="text: products().length"></span>

Controllo di flusso Bindings

La gamma di prodotti può quindi essere dati associato a un elemento DOM, dove può essere utilizzato come modello anonimo per visualizzare l'elenco. Il seguente codice HTML mostra che il tag ul viene utilizzata l'associazione di controllo di flusso foreach per associare i prodotti:

<ul data-bind="foreach:products">

  <li class="guitarListCompact">

    <div class="photoContainer">

      <img data-bind="visible: photoUrl, attr: { src: photoUrl }"

        class="photoThumbnail"></img>

    </div>

    <div data-bind="text: salePrice"></div>

  </li>

</ul>

Gli elementi all'interno del tag ul verranno utilizzati per il modello di ogni prodotto. All'interno di foreach, il contesto dati passa anche dalla radice oggetto showroomViewModel a ogni singolo prodotto. Ecco perché gli elementi DOM interni si possono legare direttamente alle proprietà photoUrl e salePrice di un prodotto.

Ci sono quattro principali associazioni di controllo di flusso: foreach, se, sinon e con. Tali associazioni di controllo consentono di definire in modo dichiarativo il controllo della logica del flusso senza creare un modello denominato. Quando il se associazione di controllo di flusso è seguita da una condizione che è truthy o l'associazione sinon è seguita da una condizione che valuta su false, il contenuto all'interno del suo blocco è vincolato e visualizzato, come illustrato di seguito:

<div data-bind="if:onSale">

  <span data-bind="text: salePrice"></span>

</div>

La con l'associazione cambia il contesto dati per qualunque oggetto si specificare. Questo è particolarmente utile durante le immersioni in oggetti grafici con più relazioni padre/figlio o ViewModels distinte all'interno di una pagina. Ad esempio, se c'è un oggetto ViewModel di vendita che è associato alla pagina e ha bambino oggetti cliente e venditore, la rilegatura potrebbe essere utilizzato per rendere le associazioni più leggibile e più facile da mantenere, come illustrato di seguito:

<div data-bind="with:customer">

  <span data-bind="text: name"></span><br/>

  <span data-bind="text: orderTotal"></span>

</div>

<div data-bind="with:salesPerson">

  <span data-bind="text: employeeNum"></span><br/>

  <span data-bind="text: name"></span>

</div>

Calcolate osservabili

Forse avete notato che la funzione prodotto definito il photoUrl come un tipo speciale di proprietà calcolate. ko.Computed definisce una funzione di associazione che valuta il valore per l'operazione di associazione dati. La proprietà calcolata viene aggiornato automaticamente quando uno qualsiasi dei osservabili di che dipende per il suo cambiamento di valutazione. Questo è particolarmente utile quando il valore non è chiaramente rappresentato in un concreto valore nell'oggetto di origine. Un altro esempio comune, oltre a creare un URL è la creazione di una proprietà fullName di firstName e lastName.

(Nota: Versioni precedenti di Knockout si riferisce alle proprietà calcolate come dependentObservable. Entrambi funzionano ancora in Knockout 2.0.0, ma mi consiglia di utilizzare la funzione calcolata più recente).

Una proprietà calcolata accetta una funzione per valutare il valore e l'oggetto che rappresenta l'oggetto a cui stai associare l'associazione. Il secondo parametro è importante perché i valori letterali di oggetto JavaScript non hanno modo di riferirsi a se stessi. In Figura 5 la parola chiave this (che rappresenta il showroomViewModel) viene passata così la funzione di osservabile dipendente può essere utilizzato per ottenere la proprietà foto. Senza questo essendo passato, la funzione foto sarebbe stata indefinita e la valutazione non riuscirebbe a produrre l'URL previsto:

this.photoUrl = ko.computed(function () {

  return photoPath +  photo();  // photo() will be undefined

});

Comprendere le proprietà fondamentali di associazione

Questa colonna hai iniziato con associazione dati usando la libreria JavaScript ad eliminazione diretta. L'aspetto più importante di Knockout è quello di comprendere le proprietà di associazione fondamentali: osservabile, observableArray e calcolata. Con questi osservabili si possono creare robuste applicazioni HTML utilizzando modelli di separazione solido. Ho anche coperto i tipi più comuni di binding incorporati e dimostrato le associazioni di controllo di flusso. Tuttavia, Knockout supporta funzionalità molto di più. La prossima volta, esplorerò binding incorporati in modo più dettagliato.

John Papa è un ex evangelist di Microsoft su Silverlight e Windows 8 squadre, dove ha ospitato il popolare show televisivo di Silverlight. Egli ha presentato a livello globale al keynote e sessioni per costruire, MIX, PDC, Tech • ed, Visual Studio Live! ed eventi DevConnections. Papa è anche un editorialista per Visual Studio Magazine (di Papa Perspective) e autore di video di formazione con Pluralsight. Seguirlo su Twitter a twitter.com/john_papa.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Steve Sanderson