5부: Knockout.js 사용하여 동적 UI 만들기
작성자: Rick Anderson
Knockout.js를 사용하여 동적 UI 만들기
이 섹션에서는 Knockout.js 사용하여 관리 보기에 기능을 추가합니다.
Knockout.js HTML 컨트롤을 데이터에 쉽게 바인딩할 수 있는 Javascript 라이브러리입니다. Knockout.js MVVM(Model-View-ViewModel) 패턴을 사용합니다.
- 모델은 비즈니스 도메인(이 경우 제품 및 주문)에 있는 데이터의 서버 쪽 표현입니다.
- 보기는 프레젠테이션 계층(HTML)입니다.
- 뷰 모델은 모델 데이터를 보유하는 Javascript 개체입니다. 뷰 모델은 UI의 코드 추상화입니다. HTML 표현에 대한 지식이 없습니다. 대신 "항목 목록"과 같은 보기의 추상 기능을 나타냅니다.
뷰는 뷰 모델에 데이터 바인딩됩니다. 뷰 모델에 대한 업데이트 보기에 자동으로 반영됩니다. 또한 view-model은 보기에서 단추 클릭과 같은 이벤트를 가져오고 주문 만들기와 같은 모델에 대한 작업을 수행합니다.
H TML 데이터, 뷰 모델, j son 및 Web API I 컨트롤러 간의 상호 작용을 보여 주는 다이어그램 H TM L 데이터 상자에는 보기라는 레이블이 지정되어 있습니다. 데이터 바인딩 레이블이 지정된 이중 화살표는 H T ML 데이터 상자를 보기 모델 상자에 연결합니다. 서버의 H TT P 요청 및 j son 모델에 레이블이 지정된 이중 화살표는 뷰 모델을 Web API 컨트롤러에 연결합니다.
먼저 뷰 모델을 정의합니다. 그런 다음 HTML 태그를 view-model에 바인딩합니다.
다음 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 페이지 아래쪽에 나타납니다.
이 페이지의 모든 스크립트는 주석으로 표시된 스크립트 태그 내부로 이동합니다.
<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
채우려면 웹 API에 AJAX 요청을 합니다. 뷰 모음에 API에 대한 기본 URI를 저장했습니다(자습서의 4부 참조).
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
// New code
var baseUri = '@ViewBag.ApiUrl';
$.getJSON(baseUri, self.products);
}
다음으로, 뷰 모델에 함수를 추가하여 제품을 만들고, 업데이트하고, 삭제합니다. 이러한 함수는 웹 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.
$(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
새 instance 전달합니다.
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
ko.applyBindings 메서드는 Knockout을 활성화하고 뷰 모델을 보기에 연결합니다.
이제 뷰 모델이 있으므로 바인딩을 만들 수 있습니다. Knockout.js HTML 요소에 특성을 추가하여 data-bind
이 작업을 수행합니다. 예를 들어 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 바인딩의 scope 내에서 발생합니다. 즉, Knockout은 배열의 각 제품에 대해 요소를 한 번 렌더링합니다 products
. 요소 내 <li>
의 모든 바인딩은 해당 제품 instance 참조합니다. 예를 들어 는 $data.Name
제품의 속성을 참조 Name
합니다.
텍스트 입력의 값을 설정하려면 바인딩을 value
사용합니다. 단추는 바인딩을 사용하여 모델 뷰의 함수에 click
바인딩됩니다. 제품 instance 각 함수에 매개 변수로 전달됩니다. 자세한 내용은 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>
애플리케이션을 실행하고 관리자 계정으로 로그인한 다음 "관리" 링크를 클릭합니다. 제품 목록이 표시되고 제품을 생성, 업데이트 또는 삭제할 수 있어야 합니다.