【ASP.NET Web API教程】2.3.5 用Knockout.js創建動態UI


注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,請先看前面的內容。

Part 5: Creating a Dynamic UI with Knockout.js
第5部分:用Knockout.js創建動態UI

本文引自:http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-entity-framework/using-web-api-with-entity-framework,-part-5

Creating a Dynamic UI with Knockout.js
用Knockout.js創建動態UI

In this section, we'll use Knockout.js to add functionality to the Admin view.
在本小節中,我們將用Knockout.js對Admin視圖添加功能。

Knockout.js is a Javascript library that makes it easy to bind HTML controls to data. Knockout.js uses the Model-View-ViewModel (MVVM) pattern.
Knockout.js是一個JavaScript庫,它讓HTML控件很容易與數據進行綁定。Knockout.js使用的是“模型-視圖-視圖模型(MVVM)”模式。

  • The model is the server-side representation of the data in the business domain (in our case, products and orders).
    模型是事務域中數據的服務器端表示(在我們的示例中,是產品和訂單)。
  • The view is the presentation layer (HTML).
    視圖是表現層(HTML)。
  • The view-model is a Javascript object that holds the model data. The view-model is a code abstraction of the UI. It has no knowledge of the HTML representation. Instead, it represents abstract features of the view, such as "a list of items".
    視圖模型是保存了模型數據的一個JavaScript對象。視圖模型是UI的一種代碼抽象。它沒有HTML表示方面的知識,但它表現了視圖的抽象特性,如“列表項”。

The view is data-bound to the view-model. Updates to the view-model are automatically reflected in the view. The view-model also gets events from the view, such as button clicks, and performs operations on the model, such as creating an order.
視圖是與視圖模型數據綁定的。對視圖模型的更新會自動地在視圖得到反映。視圖模型也會獲取視圖的事件,如按鈕點擊,並在模型上執行操作(見圖2-23)。

WebAPI2-23

圖2-23. 模型-視圖-視圖模型之間的關系

First we'll define the view-model. After that, we will bind the HTML markup to the view-model.
首先,我們要定義視圖模型。之后,要將HTML標記與視圖模型進行綁定。

Add the following Razor section to Admin.cshtml:
對Admin.cshtml添加以下Razor片段:

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

You can add this section anywhere in the file. When the view is rendered, the section appears at the bottom of the HTML page, right before the closing </body> tag.
可以把這個片斷添加到文件的任何地方。當視圖被渲染時,這個片段會出現在HTML頁面的底部,</body>關閉標簽的前面。

All of the script for this page will go inside the script tag indicated by the comment:
用於這個頁面的所有腳本都被放在由以下注釋所指示的script標簽中:

<script type="text/javascript"> 
    // View-model will go here
    // 視圖模型會放在這兒
 </script>

First, define a view-model class:
首先,定義一個視圖模型類:

function ProductsViewModel() { 
    var self = this; 
    self.products = ko.observableArray(); 
}

ko.observableArray is a special kind of object in Knockout, called an observable. From the Knockout.js documentation: An observable is a “JavaScript object that can notify subscribers about changes.” When the contents of an observable change, the view is automatically updated to match.
ko.observableArray是Knockout中的一種叫做observable的特殊對象(請將這種observable對象稱為可見對象。這種對象往往作為視圖模型與視圖進行交互,對視圖而言,它是透明可見的,故稱為可見對象。在以下翻譯中,都將這種observable對象稱為可見對象 — 譯者注)。根據Knockout.js文檔的描述:可見對象是一種“能夠通知訂戶數據變化情況的JavaScript對象”。當一個可見對象的內容發生變化時,視圖會自動地進行匹配更新。

To populate the products array, make an AJAX request to the web API. Recall that we stored the base URI for the API in the view bag (see Part 4 of the tutorial).
為了填充Products數組,需要形成一個發送到Web API的請求。調回我們在視圖包(View Bag)中存儲的、用於此API的基URI(見本教程的第4部分)。

function ProductsViewModel() { 
    var self = this; 
    self.products = ko.observableArray(); 
// New code // 新代碼 var baseUri = '@ViewBag.ApiUrl'; $.getJSON(baseUri, self.products); }

Next, add functions to the view-model to create, update, and delete products. These functions submit AJAX calls to the web API and use the results to update the view-model.
下一步,對視圖模型添加創建、更新以及刪除產品的函數。這些函數會對Web API遞交AJAX調用,並使用(所得到的)結果對視圖模型進行更新。

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. // 如果表單數據有效,把序列化的表單數據遞交給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); }

Now the most important part: When the DOM is fulled loaded, call the ko.applyBindings function and pass in a new instance of the ProductsViewModel:
現在,最重要的部分:當DOM全部裝載時,調用ko.applyBindings函數,並在其中傳遞一個新的ProductsViewModel實例:

$(document).ready(function () {
    ko.applyBindings(new ProductsViewModel());
})

The ko.applyBindings method activates Knockout and wires up the view-model to the view.
ko.applyBindings方法會激活Knockout,並將視圖模型與視圖連接起來。

Now that we have a view-model, we can create the bindings. In Knockout.js, you do this by adding data-bind attributes to HTML elements. For example, to bind an HTML list to an array, use the foreach binding:
現在,我們有了一個視圖模型,於是可以創建綁定(這里的綁定含義是將視圖模型中的數據項與視圖中的各個HTML控件進行綁定 — 譯者注)。在Knockout.js中,通過把data-bind標簽屬性(標簽屬性是指HTML元素的屬性,這樣翻譯的目的也是與類的屬性有所區別 — 譯者注)添加到HTML元素的辦法來做這件事。例如,要把一個HTML列表綁定到一個數據,使用foreach綁定:

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

The foreach binding iterates through the array and creates child elements for each object in the array. Bindings on the child elements can refer to properties on the array objects.
foreach綁定會遍歷數組,並為數組中的每個對象創建子元素。在子元素上的綁定可以指向數組對象上的屬性。

Add the following bindings to the "update-products" list:
對“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>

The <li> element occurs within the scope of the foreach binding. That means Knockout will render the element once for each product in the products array. All of the bindings within the <li> element refer to that product instance. For example, $data.Name refers to the Name property on the product.
<li>元素出現在foreach綁定的范圍之內。這意味着Knockout會對products數組中的每個產品渲染一個元素。在<li>元素中的所有綁定指向這個產品實例。例如,$data.Name是指該產品上的Name屬性。

To set the values of the text inputs, use the value binding. The buttons are bound to functions on the model-view, using the click binding. The product instance is passed as a parameter to each function. For more information, the Knockout.js documentation has good descriptions of the various bindings.
設置文本輸入框的值,要使用value綁定。按鈕要綁定到視圖模型上的函數,需使用click綁定。產品實例是作為參數傳遞給每個函數的。對於更多信息,Knockout.js文檔對各種綁定有很好的描述。

Next, add a binding for the submit event on the Add Product form:
下一步,為“添加產品”表單上的submit(遞交)事件添加一個綁定:

<form id="addProduct" data-bind="submit: create">

This binding calls the create function on the view-model to create a new product.
這個綁定調用視圖模型上的create函數,以創建一個新產品。

Here is the complete code for the Admin view:
以下是Admin視圖的完整代碼:

@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 // 如果有效,把序列化的表單數據遞交(post)給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 // 先從服務器刪除,然后從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>

Run the application, log in with the Administrator account, and click the "Admin" link. You should see the list of products, and be able to create, update, or delete products.
運行應用程序,用Administrator賬號登錄,並點擊“Admin”鏈接。應當看到產品列表,並能夠創建、更新或刪除產品。

看完此文如果覺得有所收獲,懇請給個推薦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM