Część 5. Tworzenie dynamicznego interfejsu użytkownika przy użyciu Knockout.js
Autor: Rick Anderson
Pobieranie ukończonego projektu
Tworzenie dynamicznego interfejsu użytkownika z użyciem biblioteki Knockout.js
W tej sekcji użyjemy Knockout.js, aby dodać funkcje do widoku Administracja.
Knockout.js to biblioteka języka JavaScript, która ułatwia powiązanie kontrolek HTML z danymi. Knockout.js używa wzorca Model-View-ViewModel (MVVM).
- Model jest reprezentacją danych po stronie serwera w domenie biznesowej (w naszym przypadku produkty i zamówienia).
- Widok jest warstwą prezentacji (HTML).
- Model widoku jest obiektem javascript, który przechowuje dane modelu. Model-widok jest abstrakcją kodu interfejsu użytkownika. Nie ma wiedzy na temat reprezentacji HTML. Zamiast tego reprezentuje abstrakcyjne funkcje widoku, takie jak "lista elementów".
Widok jest powiązany z danymi z modelem widoku. Aktualizacje do modelu widoku są automatycznie odzwierciedlane w widoku. Model-widok pobiera również zdarzenia z widoku, takie jak kliknięcia przycisków, i wykonuje operacje na modelu, takie jak tworzenie zamówienia.
Diagram przedstawiający interakcję między danymi H T M L, modelem widoku, synem i kontrolerem Web A P I. Pole danych H T M L jest oznaczone etykietą widok. Podwójna strzałka z etykietą powiązania danych łączy pole danych H T M L z polem modelu widoku. Podwójna strzałka z etykietą H T T P P i model syna j z serwera łączy model widoku z kontrolerem Web A P I.
Najpierw zdefiniujemy model widoku. Następnie utworzymy powiązanie znaczników HTML z modelem widoku.
Dodaj następującą sekcję Razor do pliku Administracja.cshtml:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.1.0.js")"></script>
<script type="text/javascript">
// View-model will go here
</script>
}
Tę sekcję można dodać w dowolnym miejscu w pliku. Gdy widok jest renderowany, sekcja zostanie wyświetlona w dolnej części strony HTML bezpośrednio przed zamykającym <tagiem /body> .
Cały skrypt dla tej strony przejdzie do tagu skryptu wskazanego przez komentarz:
<script type="text/javascript">
// View-model will go here
</script>
Najpierw zdefiniuj klasę modelu widoku:
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
}
ko.observableArray jest specjalnym rodzajem obiektu w Knockout, nazywanym obserwowalnym. Z dokumentacjiKnockout.js: Można zaobserwować to "obiekt JavaScript, który może powiadamiać subskrybentów o zmianach". Gdy zawartość obserwowalnej zmiany, widok jest automatycznie aktualizowany w celu dopasowania.
Aby wypełnić tablicę products
, utwórz żądanie AJAX do internetowego interfejsu API. Pamiętaj, że podstawowy identyfikator URI interfejsu API jest przechowywany w torbie widoku (zobacz część 4 samouczka).
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
// New code
var baseUri = '@ViewBag.ApiUrl';
$.getJSON(baseUri, self.products);
}
Następnie dodaj funkcje do modelu widoku, aby tworzyć, aktualizować i usuwać produkty. Te funkcje przesyłają wywołania AJAX do internetowego interfejsu API i używają wyników do aktualizowania modelu widoku.
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
// New code
self.create = function (formElement) {
// If the form data is valid, post the serialized form data to the web API.
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) {
// Add the new product to the view-model.
self.products.push(o);
});
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the view-model.
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
Teraz najważniejszą częścią: Po załadowaniu modelu DOM wywołaj funkcję ko.applyBindings i przekaż nowe wystąpienie elementu ProductsViewModel
:
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
Metoda ko.applyBindings aktywuje knockout i podłącza model widoku do widoku.
Teraz, gdy mamy już model widoku, możemy utworzyć powiązania. W Knockout.js można to zrobić, dodając data-bind
atrybuty do elementów HTML. Aby na przykład powiązać listę HTML z tablicą, użyj foreach
powiązania:
<ul id="update-products" data-bind="foreach: products">
foreach
Powiązanie iteruje tablicę i tworzy elementy podrzędne dla każdego obiektu w tablicy. Powiązania elementów podrzędnych mogą odwoływać się do właściwości obiektów tablicowych.
Dodaj następujące powiązania do listy "update-products":
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
Element <li>
występuje w zakresie powiązania foreach . Oznacza to, że funkcja Knockout będzie renderować element raz dla każdego produktu w tablicy products
. Wszystkie powiązania w elemecie <li>
odwołują się do tego wystąpienia produktu. Na przykład $data.Name
odwołuje się do Name
właściwości produktu.
Aby ustawić wartości danych wejściowych tekstu, użyj value
powiązania. Przyciski są powiązane z funkcjami w widoku modelu przy użyciu click
powiązania. Wystąpienie produktu jest przekazywane jako parametr do każdej funkcji. Aby uzyskać więcej informacji, dokumentacjaKnockout.js zawiera dobre opisy różnych powiązań.
Następnie dodaj powiązanie zdarzenia przesyłania w formularzu Dodaj produkt:
<form id="addProduct" data-bind="submit: create">
To powiązanie wywołuje create
funkcję w modelu widoku, aby utworzyć nowy produkt.
Oto kompletny kod widoku Administracja:
@model ProductStore.Models.Product
@{
ViewBag.Title = "Admin";
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.0.0.js")"></script>
<script type="text/javascript">
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
self.create = function (formElement) {
// If valid, post the serialized form data to the web api
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) { self.products.push(o); });
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the UI
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
</script>
}
<h2>Admin</h2>
<div class="content">
<div class="float-left">
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
</div>
<div class="float-right">
<h2>Add New Product</h2>
<form id="addProduct" data-bind="submit: create">
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
@Html.EditorForModel()
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
</div>
</div>
Uruchom aplikację, zaloguj się przy użyciu konta administratora i kliknij link "Administracja". Powinna zostać wyświetlona lista produktów i możliwość tworzenia, aktualizowania lub usuwania produktów.