本篇使用Knockout在MVC下实现"Hello World",对应的官网实例在这里。
View视图
Knockout的一个特点是:声明式绑定,即Declarative bindings。暂且不管业务逻辑,先把关注点放在界面UI上,即"MVVM"模式中的第二个"V", 也就是View视图。根据Knockout的语法,创建如下界面:
<div> <p>First name:<input data-bind="value: firstName" /></p> <p>Last name:<input data-bind="value: lastName" /></p> <h2>Hello, <span data-bind="text: fullName"></span>!</h2> </div>
Model领域模型
对于MVC来说,应该有一个与之对应的领域模型,即"MVVM"模式中的第一个"M":
namespace MyMVCKnockout.Models { public class HelloWorldModel { public string FirstName { get; set; } public string LastName { get; set; } public string FullName { get { return FirstName + " " + LastName; } } } }
接下来,让HelloWorld控制器的GetHelloWorld方法提供Json格式的返回数据:
using System.Web.Mvc; using MyMVCKnockout.Models; namespace MyMVCKnockout.Controllers { public class HelloWorldController : Controller { public ActionResult Index() { return View(); } public JsonResult GetHelloWorld() { var model = new HelloWorldModel() { FirstName = "darren", LastName = "ji" }; return Json(model, JsonRequestBehavior.AllowGet); } } }
View Model视图模型
现在,领域模型有了,视图UI也具备了,接下来,需要让View Model与视图UI绑定起来。绑定的目的是:当视图UI有变化的时候,View Model也会变化,反之亦然。也就是Knockout宣称的"Elegant dependency tracking",优雅的依赖追踪。如何做到呢?
大致二步。首先,Knockout通过使用ko.observable()、ko.observableArray()方法让View Model的属性、集合属性具有"Observable"特点。然后,使用ko.applyBindings()把View Model和视图UI绑定起来。最终做到了"Elegant dependency tracking"。
第一步:创建View Model,并使相关属性具备"Observable"特点。
function ViewModel() { var self = this; self.firstName = ko.observable(""); self.lastName = ko.observable(""); self.fullName = ko.computed(function () { return self.firstName() + " " + self.lastName(); }); }
以上,firstName和lastName具备了"Observable"特点,fullName值通过ko.computed()方法计算而得。
第二步:使用ko.applyBindings()绑定View Model和视图UI。
$(function () { var myViewModel = new ViewModel(); ko.applyBindings(myViewModel); $.getJSON('@Url.Action("GetHelloWorld","HelloWorld")', function (data) { myViewModel.firstName(data.FirstName); myViewModel.lastName(data.LastName); }); });
以上,通过ko.applyBindings(myViewModel),实现了View Model和视图UI的绑定。如果想把不同的View Model绑定到不同的视图UI,应使用ko.applyBindings(myViewModel, document.getElementById(‘someElementId’))方法。
ViewModel中,fristName,lastName的初始值为空,以上通过$.getJSON()的回调函数,给fristName,lastName重新赋了值。从最终显示的界面效果来看,通过Knockout的绑定机制,随着View Model的变化,其对应的UI内容也确实发生了改变。
HelloWorld/Index.cshtml视图完整如下:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/Scripts/jquery-1.8.2.js"></script> <script src="~/Scripts/knockout-3.1.0.js"></script> <script type="text/javascript"> $(function () { var myViewModel = new ViewModel(); ko.applyBindings(myViewModel); $.getJSON('@Url.Action("GetHelloWorld","HelloWorld")', function (data) { myViewModel.firstName(data.FirstName); myViewModel.lastName(data.LastName); }); }); function ViewModel() { var self = this; self.firstName = ko.observable(""); self.lastName = ko.observable(""); self.fullName = ko.computed(function () { return self.firstName() + " " + self.lastName(); }); } </script> </head> <body> <div> <p>First name:<input data-bind="value: firstName" /></p> <p>Last name:<input data-bind="value: lastName" /></p> <h2>Hello, <span data-bind="text: fullName"></span>!</h2> </div> </body> </html>
“Knockout官网实例在MVC下的实现”系列包括: