Bölüm 7: Ana Sayfa Oluşturma

tarafından Rick Anderson

Tamamlanan Projeyi İndir

Ana Sayfayı Oluşturma

Bu bölümde ana uygulama sayfasını oluşturacaksınız. Bu sayfa Yönetici sayfadan daha karmaşık olacaktır, bu nedenle bu sayfaya birkaç adımda yaklaşacağız. Bu arada, daha gelişmiş Knockout.js tekniklerini göreceksiniz. Sayfanın temel düzeni aşağıdadır:

Ana sayfanın ürünler, sepet, siparişler ve sipariş ayrıntıları öğeleri arasındaki etkileşimin diyagramı.

Ana sayfanın ürünler, sepet, siparişler ve sipariş ayrıntıları öğeleri arasındaki etkileşimin diyagramı. Products öğesi, items öğesine işaret eden bir okla GET A P I / products olarak etiketlenmiştir. Items öğesi orders öğesine POST A P I / orders etiketli bir okla bağlanır. orders öğesi GET A P I / orders etiketli bir okla details öğesine bağlanır. Details öğesi lebeled GET A P I / orders / i d.

  • "Ürünler" bir dizi ürün içerir.
  • "Sepet", miktarları olan bir ürün dizisini barındırıyor. "Sepete Ekle" seçeneğine tıklanması sepeti güncelleştirir.
  • "Siparişler" bir dizi sipariş kimliği içerir.
  • "Ayrıntılar" bir sipariş ayrıntısı içerir; bu bir dizi öğedir (miktarları olan ürünler)

Başlangıç olarak HTML'de veri bağlaması veya betik olmadan bazı temel düzenleri tanımlayacağız. Views/Home/Index.cshtml dosyasını açın ve tüm içeriği aşağıdakilerle değiştirin:

<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>

Ardından, bir Betikler bölümü ekleyin ve boş bir görünüm modeli oluşturun:

@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>
}

Daha önce çizilen tasarıma göre, görünüm modelimizin ürünler, sepet, siparişler ve ayrıntılar için gözlemlenebilir öğelere ihtiyacı vardır. Nesnesine aşağıdaki değişkenleri AppViewModel ekleyin:

self.products = ko.observableArray();
self.cart = ko.observableArray();
self.orders = ko.observableArray();
self.details = ko.observable();

Kullanıcılar ürünler listesindeki öğeleri sepete ekleyebilir ve sepetten öğe kaldırabilir. Bu işlevleri kapsüllemek için bir ürünü temsil eden başka bir görünüm modeli sınıfı oluşturacağız. Aşağıdaki kodu AppViewModel dosyasına ekleyin:

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);
        };
    }
}

sınıfı, ProductViewModel ürünü sepete taşımak ve sepetten taşımak için kullanılan iki işlev içerir: addItemToCart ürünün bir birimini sepete ekler ve removeAllFromCart ürünün tüm miktarlarını kaldırır.

Kullanıcılar mevcut bir siparişi seçebilir ve sipariş ayrıntılarını alabilir. Bu işlevi başka bir görünüm modeline kapsülleyeceğiz:

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);
            })
        });
    };
}

OrderDetailsViewModel bir siparişle başlatılır ve sunucuya bir AJAX isteği göndererek sipariş ayrıntılarını getirir.

Ayrıca üzerindeki özelliğine totalOrderDetailsViewModelde dikkat edin. Bu özellik, hesaplanan gözlemlenebilir olarak adlandırılan özel bir gözlemlenebilir türüdür. Adından da anlaşılacağı gibi, hesaplanan gözlemlenebilir veriler hesaplanan bir değere (bu örnekte siparişin toplam maliyeti) bağlanmanızı sağlar.

Ardından, bu işlevleri öğesine AppViewModelekleyin:

  • resetCart sepetten tüm öğeleri kaldırır.
  • getDetails siparişin ayrıntılarını alır (listeye yeni OrderDetailsViewModeldetails bir sipariş göndererek).
  • createOrder yeni bir sipariş oluşturur ve sepeti boşalttır.
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);
            }  
        });
    };
};

Son olarak, ürünler ve siparişler için AJAX istekleri yaparak görünüm modelini başlatın:

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);
};

Pekâlâ, bu çok fazla kod ama bunu adım adım oluşturduğumuz için tasarımın net olduğunu umuyoruz. Artık HTML'ye bazı Knockout.js bağlamaları ekleyebiliriz.

Ürünler

Ürün listesinin bağlamaları şunlardır:

<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>

Bu, products dizisini yineler ve adı ve fiyatı görüntüler. "Siparişe Ekle" düğmesi yalnızca kullanıcı oturum açtığında görünür.

"Siparişe Ekle" düğmesi, ürünün örneğini ProductViewModel çağırıraddItemToCart. Bu, Knockout.js güzel bir özelliğini gösterir: Görünüm modeli başka görünüm modelleri içeriyorsa, bağlamaları iç modele uygulayabilirsiniz. Bu örnekte içindeki bağlamalar foreach örneklerin ProductViewModel her birine uygulanır. Bu yaklaşım, tüm işlevleri tek bir görünüm modeline yerleştirmekten çok daha temizdir.

Sepet

Sepet için bağlamalar şunlardır:

<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"/>

Bu, sepet dizisi üzerinde yinelenir ve adı, fiyatı ve miktarı görüntüler. "Kaldır" bağlantısının ve "Sipariş Oluştur" düğmesinin görünüm modeli işlevlerine bağlı olduğunu unutmayın.

Siparişler

Sipariş listesinin bağlamaları şunlardır:

<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>

Bu, siparişler üzerinde yinelenir ve sipariş kimliğini gösterir. Bağlantıdaki tıklama olayı işleve getDetails bağlıdır.

Sipariş Ayrıntıları

Sipariş ayrıntıları için bağlamalar şunlardır:

<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>

Bu, siparişteki öğeleri yineler ve ürünü, fiyatı ve miktarı görüntüler. Çevresindeki div yalnızca details dizisinde bir veya daha fazla öğe varsa görünür.

Sonuç

Bu öğreticide veritabanıyla iletişim kurmak için Entity Framework kullanan bir uygulama oluşturdunuz ve veri katmanının üstünde genel kullanıma yönelik bir arabirim sağlamak için Web API'sini ASP.NET. HTML sayfalarını işlemek için ASP.NET MVC 4 ve sayfa yeniden yüklemeleri olmadan dinamik etkileşimler sağlamak için Knockout.js artı jQuery kullanıyoruz.

Ek kaynaklar: