Část 7: Vytvoření hlavní stránky
Rick Anderson
Vytvoření hlavní stránky
V této části vytvoříte hlavní stránku aplikace. Tato stránka bude složitější než stránka Správa, takže se k ní budeme blížit v několika krocích. Na této cestě uvidíte některé pokročilejší techniky Knockout.js. Tady je základní rozložení stránky:
Diagram interakce mezi prvky hlavní stránky, košíkem, objednávkami a podrobnostmi objednávek Element products je označený GET A P I / products se šipkou ukazující na prvek items. Element items je připojen k prvku orders pomocí šipky označené POST A P I / orders. Element orders je připojený k prvku details pomocí šipky označené GET A P I / orders. Element details je označen GET A P I / orders / i d.
- "Produkty" obsahují řadu produktů.
- "Košík" obsahuje pole produktů s množstvím. Kliknutím na Přidat do košíku se košík aktualizuje.
- "Objednávky" obsahují pole ID objednávek.
- "Podrobnosti" obsahují podrobnosti objednávky, což je pole položek (produkty s množstvím).
Začneme definováním základního rozložení v HTML bez datové vazby nebo skriptu. Otevřete soubor Views/Home/Index.cshtml a nahraďte veškerý obsah následujícím kódem:
<div class="content">
<!-- List of products -->
<div class="float-left">
<h1>Products</h1>
<ul id="products">
</ul>
</div>
<!-- Cart -->
<div id="cart" class="float-right">
<h1>Your Cart</h1>
<table class="details ui-widget-content">
</table>
<input type="button" value="Create Order"/>
</div>
</div>
<div id="orders-area" class="content" >
<!-- List of orders -->
<div class="float-left">
<h1>Your Orders</h1>
<ul id="orders">
</ul>
</div>
<!-- Order Details -->
<div id="order-details" class="float-right">
<h2>Order #<span></span></h2>
<table class="details ui-widget-content">
</table>
<p>Total: <span></span></p>
</div>
</div>
Dále přidejte oddíl Scripts (Skripty) a vytvořte prázdný view-model:
@section Scripts {
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.1.0.js")"></script>
<script type="text/javascript">
function AppViewModel() {
var self = this;
self.loggedIn = @(Request.IsAuthenticated ? "true" : "false");
}
$(document).ready(function () {
ko.applyBindings(new AppViewModel());
});
</script>
}
Na základě návrhu načrtnutého dříve potřebuje náš model zobrazení sledovatelné údaje týkající se produktů, košíků, objednávek a podrobností. Přidejte do objektu AppViewModel
následující proměnné:
self.products = ko.observableArray();
self.cart = ko.observableArray();
self.orders = ko.observableArray();
self.details = ko.observable();
Uživatelé můžou přidávat položky ze seznamu produktů do košíku a odebírat položky z košíku. K zapouzdření těchto funkcí vytvoříme další třídu view-model, která představuje produkt. Do souboru AppViewModel
přidejte následující kód:
function AppViewModel() {
// ...
// NEW CODE
function ProductViewModel(root, product) {
var self = this;
self.ProductId = product.Id;
self.Name = product.Name;
self.Price = product.Price;
self.Quantity = ko.observable(0);
self.addItemToCart = function () {
var qty = self.Quantity();
if (qty == 0) {
root.cart.push(self);
}
self.Quantity(qty + 1);
};
self.removeAllFromCart = function () {
self.Quantity(0);
root.cart.remove(self);
};
}
}
Třída ProductViewModel
obsahuje dvě funkce, které se používají k přesunu produktu do a z košíku: addItemToCart
přidá do košíku jednu jednotku produktu a removeAllFromCart
odebere všechna množství produktu.
Uživatelé můžou vybrat existující objednávku a získat podrobnosti o objednávce. Tuto funkci zapouzdřeme do jiného modelu zobrazení:
function AppViewModel() {
// ...
// NEW CODE
function OrderDetailsViewModel(order) {
var self = this;
self.items = ko.observableArray();
self.Id = order.Id;
self.total = ko.computed(function () {
var sum = 0;
$.each(self.items(), function (index, item) {
sum += item.Price * item.Quantity;
});
return '$' + sum.toFixed(2);
});
$.getJSON("/api/orders/" + order.Id, function (order) {
$.each(order.Details, function (index, item) {
self.items.push(item);
})
});
};
}
Inicializuje OrderDetailsViewModel
se s objednávkou a načte podrobnosti objednávky odesláním požadavku AJAX na server.
Všimněte si total
také vlastnosti .OrderDetailsViewModel
Tato vlastnost je speciální druh pozorovatelného, kterému se říká vypočítaný pozorovatelný. Jak název napovídá, vypočítaný pozorovatelný umožňuje vytvořit vazbu dat na vypočítanou hodnotu – v tomto případě celkové náklady na objednávku.
Dále přidejte tyto funkce do AppViewModel
:
resetCart
odebere všechny položky z košíku.getDetails
získá podrobnosti o objednávce (vložením novéhoOrderDetailsViewModel
příkazu dodetails
seznamu).createOrder
vytvoří novou objednávku a vyprázdní košík.
function AppViewModel() {
// ...
// NEW CODE
self.resetCart = function() {
var items = self.cart.removeAll();
$.each(items, function (index, product) {
product.Quantity(0);
});
}
self.getDetails = function (order) {
self.details(new OrderDetailsViewModel(order));
}
self.createOrder = function () {
var jqxhr = $.ajax({
type: 'POST',
url: "api/orders",
contentType: 'application/json; charset=utf-8',
data: ko.toJSON({ Details: self.cart }),
dataType: "json",
success: function (newOrder) {
self.resetCart();
self.orders.push(newOrder);
},
error: function (jqXHR, textStatus, errorThrown) {
self.errorMessage(errorThrown);
}
});
};
};
Nakonec inicializujte model zobrazení tak, že odešlete požadavky AJAX na produkty a objednávky:
function AppViewModel() {
// ...
// NEW CODE
// Initialize the view-model.
$.getJSON("/api/products", function (products) {
$.each(products, function (index, product) {
self.products.push(new ProductViewModel(self, product));
})
});
$.getJSON("api/orders", self.orders);
};
Dobře, to je hodně kódu, ale vytvořili jsme ho krok za krokem, takže doufejme, že návrh je jasný. Teď můžeme do HTML přidat několik Knockout.js vazeb.
Produkty
Tady jsou vazby pro seznam produktů:
<ul id="products" data-bind="foreach: products">
<li>
<div>
<span data-bind="text: Name"></span>
<span class="price" data-bind="text: '$' + Price"></span>
</div>
<div data-bind="if: $parent.loggedIn">
<button data-bind="click: addItemToCart">Add to Order</button>
</div>
</li>
</ul>
To iteruje pole produktů a zobrazí název a cenu. Tlačítko "Přidat do objednávky" se zobrazí, jenom když je uživatel přihlášený.
Tlačítko Add to Order (Přidat do objednávky) volá addItemToCart
ProductViewModel
instanci produktu. To ukazuje dobrou funkci Knockout.js: Pokud view-model obsahuje další modely zobrazení, můžete použít vazby na vnitřní model. V tomto příkladu se vazby v rámci objektu foreach
použijí na každou instanci ProductViewModel
. Tento přístup je mnohem čistší než uvedení všech funkcí do jediného modelu zobrazení.
Košík
Tady jsou vazby pro košík:
<div id="cart" class="float-right" data-bind="visible: cart().length > 0">
<h1>Your Cart</h1>
<table class="details ui-widget-content">
<thead>
<tr><td>Item</td><td>Price</td><td>Quantity</td><td></td></tr>
</thead>
<tbody data-bind="foreach: cart">
<tr>
<td><span data-bind="text: $data.Name"></span></td>
<td>$<span data-bind="text: $data.Price"></span></td>
<td class="qty"><span data-bind="text: $data.Quantity()"></span></td>
<td><a href="#" data-bind="click: removeAllFromCart">Remove</a></td>
</tr>
</tbody>
</table>
<input type="button" data-bind="click: createOrder" value="Create Order"/>
Iteruje se v poli košíku a zobrazí se název, cena a množství. Všimněte si, že odkaz "Odebrat" a tlačítko "Vytvořit objednávku" jsou vázány na funkce view-model.
Orders (Objednávky)
Tady jsou vazby pro seznam objednávek:
<h1>Your Orders</h1>
<ul id="orders" data-bind="foreach: orders">
<li class="ui-widget-content">
<a href="#" data-bind="click: $root.getDetails">
Order # <span data-bind="text: $data.Id"></span></a>
</li>
</ul>
To iteruje objednávky a zobrazuje ID objednávky. Událost click na odkazu je vázaná na getDetails
funkci .
Podrobnosti objednávky
Tady jsou vazby pro podrobnosti objednávky:
<div id="order-details" class="float-right" data-bind="if: details()">
<h2>Order #<span data-bind="text: details().Id"></span></h2>
<table class="details ui-widget-content">
<thead>
<tr><td>Item</td><td>Price</td><td>Quantity</td><td>Subtotal</td></tr>
</thead>
<tbody data-bind="foreach: details().items">
<tr>
<td><span data-bind="text: $data.Product"></span></td>
<td><span data-bind="text: $data.Price"></span></td>
<td><span data-bind="text: $data.Quantity"></span></td>
<td>
<span data-bind="text: ($data.Price * $data.Quantity).toFixed(2)"></span>
</td>
</tr>
</tbody>
</table>
<p>Total: <span data-bind="text: details().total"></span></p>
</div>
Tím se iteruje položky v objednávce a zobrazí se produkt, cena a množství. Okolní div je viditelný pouze v případě, že pole podrobností obsahuje jednu nebo více položek.
Závěr
V tomto kurzu jste vytvořili aplikaci, která ke komunikaci s databází používá Entity Framework, a ASP.NET webové rozhraní API, aby poskytovalo veřejné rozhraní nad datovou vrstvou. K vykreslení stránek HTML používáme ASP.NET MVC 4 a Knockout.js a jQuery k zajištění dynamických interakcí bez opětovného načtení stránky.
Další prostředky: