共用方式為


第 5 部分:使用 Knockout.js 建立動態 UI

作者:Rick Anderson

下載已完成的專案

使用 Knockout.js 建立動態 UI

在本節中,我們將使用Knockout.js將功能新增至管理員檢視。

Knockout.js 是 JAVAscript 程式庫,可讓您輕鬆地將 HTML 控制項系結至資料。 Knockout.js使用 Model-View-ViewModel (MVVM) 模式。

  • 此模型是商務領域中資料的伺服器端標記法,在我們的案例中為產品與訂單) (。
  • 檢視是呈現層 (HTML) 。
  • 檢視模型是保留模型資料的 JAVAscript 物件。 檢視模型是 UI 的程式碼抽象概念。 它不知道 HTML 標記法。 相反地,它代表檢視的抽象特徵,例如「專案清單」。

檢視會系結至檢視模型的資料。 檢視模型更新會自動反映在檢視中。 檢視模型也會從檢視取得事件,例如按鈕點選,並在模型上執行作業,例如建立訂單。

H T M L 資料、檢視模型、j son 和 Web A P I 控制器之間的互動圖表。

此圖顯示 H T M L 資料、檢視模型、j son 和 Web A P I 控制器之間的互動。 H T M L 資料方塊已標示為檢視。 標示為雙箭號的資料系結會將 H T M L 資料箱連結到檢視模型方塊。 從伺服器標示為 H T T P 要求和 j son 模型的雙箭號會將檢視模型連結至 Web A P I 控制器。

首先,我們將定義檢視模型。 之後,我們會將 HTML 標籤系結至檢視模型。

將下列 Razor 區段新增至 管理員.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>
}

您可以在檔案中的任何位置新增此區段。 轉譯檢視時,區段會出現在 HTML 頁面底部的結尾 < /body > 標籤之前。

此頁面的所有腳本都會進入批註所指示的腳本標籤內:

<script type="text/javascript">
  // View-model will go here
  </script>

首先,定義檢視模型類別:

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

ko.observableArray 是一種特殊種類的物件,稱為 可觀察。 從 Knockout.js檔中:可觀察的是「JavaScript 物件,可通知訂閱者有關變更」。當可觀察變更的內容時,檢視會自動更新以符合。

若要填入 products 陣列,請向 Web API 提出 AJAX 要求。 回想一下,我們已將 API 的基底 URI 儲存在檢視包中, (請參閱教學課程的第 4 部分) 。

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

    // New code
    var baseUri = '@ViewBag.ApiUrl';
    $.getJSON(baseUri, self.products);
}

接下來,將函式新增至檢視模型,以建立、更新和刪除產品。 這些函式會將 AJAX 呼叫提交至 Web API,並使用結果來更新檢視模型。

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

現在最重要的部分:載入 DOM 時,呼叫 ko.applyBindings 函式並傳入 的新實例 ProductsViewModel

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

ko.applyBindings方法會啟動一個將檢視模型連線到檢視。

現在我們有檢視模型,我們可以建立系結。 在Knockout.js中,您會將屬性新增 data-bind 至 HTML 元素來執行此動作。 例如,若要將 HTML 清單系結至陣列,請使用系 foreach 結:

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

foreach 結會逐一查看陣列,並為數組中的每個物件建立子專案。 子項目上的系結可以參考陣列物件上的屬性。

將下列系結新增至 「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>

元素 <li> 會在 foreach 系結的範圍內發生。 這表示會為數組中的每個 products 產品轉譯元素一次。 元素內 <li> 的所有系結都會參考該產品實例。 例如, $data.Name 參考 Name 產品上的 屬性。

若要設定文字輸入的值,請使用系 value 結。 按鈕會使用 click 系結系結,系結至模型檢視上的函式。 產品實例會當做參數傳遞至每個函式。 如需詳細資訊, Knockout.js檔 有各種系結的良好描述。

接下來,在 [新增產品] 表單上新增 提交 事件的系結:

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

此系結會在檢視模型上呼叫 函 create 式,以建立新產品。

以下是管理員檢視的完整程式碼:

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

執行應用程式、使用系統管理員帳戶登入,然後按一下 [管理員] 連結。 您應該會看到產品清單,並能夠建立、更新或刪除產品。