从人类不断进化的历程中,我们可以总结出一个规律,那就是分工越来越细。每个人的精力有限,关注的点越集中就能够把一件事情做到极致。程序最开始的时候是面向过程的,后来发现职责不明确,于是一步一步演化成了面向对象。ASP是数据与界面混杂的,ASP.NET 就划分了前后端,但是还不够好,因为处理逻辑不集中,耦合性太改,不便于测试。WPF之所以能取代原来的winform,有人说WPF能够做很多漂亮的界面,这只是很小的一个原因,真正的原因在于WPF做到了很好的界面与逻辑的分离,并且很优雅地做了数据与视图的绑定。
MVC模式中,视图是可以直接和模型进行交互的,这就给用户体验带了了很大的提升,ASP.NET MVC 中部分视图的使用,能够很好地实现布局刷新的效果,从分页,查询等等各个方面带来优质的用户体验。当我们因为MVC给我们带来的好处欣喜若狂时,我们脑海里产生了一个疑问,我们的WEB应用能不能像WPF一样呢,实现DOM对象与数据的直接绑定呢,这样的话我们就不必再写很多javascript代码去响应DOM的值发生改变的事件,虽然jquery已经非常强大,很多的事情几句话就能搞定。
这时候KnockOut就横空出世了,它完美地解决了DOM与数据模型绑定的问题。不过这里不得不提一句,Knockout并不是唯一一个实现了MVVM模式的JS库,而且也不是第一个,ExtJs才是第一个实现了MVVM的,ExtJs是重量级(有人说是超重量级)的前端企业级库,但不及Jquery锋利(有一本书叫锋利的Jquery),建议大家阅读。
今天写了个几个例子,演示了这个变化过程。
1.传统的数据绑定形式。
<script type="text/javascript">
$(document).ready(function () {
function Account(bank, accNo, type, status) {
var self = this;
self.bank = bank;
self.accNo = accNo;
self.type = type;
self.status = status;
};
var myAcc = new Account("Bank1", "12345678", "Saving", "Active");
// To add this
$("#accontBankName").text(myAcc.bank);
$("#accountNum").text(myAcc.accNo);
$("#accountType").text(myAcc.type);
$("#accountStatus").text(myAcc.status);
});
</script>
<h2>My Account </h2>
<span>Bank Name:</span><span id="accontBankName"></span>
<br />
<span>Account Number:</span><span id="accountNum"></span>
<br />
<span>Account Type:</span><span id="accountType"></span>
<br />
<span>Status:</span><span id="accountStatus"></span>
效果如下:
这里作为演示,数据是固定的,实际情况下我们会使用jquery发起GET请求从后台去取数据。
2.使用knockOut绑定数据
<script type="text/javascript">
$(document).ready(function () {
function Account(bank, accNo, type, status) {
var self = this;
self.bank = bank;
self.accNo = accNo;
self.type = type;
self.status = status;
};
function AccountViewModel() {
var self = this;
self.account = new Account("sbi", "12345678", "Saving", "Active");
};
ko.applyBindings(new AccountViewModel());
//ko.applyBindings(new Account("sbi", "12345678", "Saving", "Active"));
});
</script>
<h2>My Account </h2>
<span>Bank Name:</span><span id="accontBankName" data-bind="text: account.bank"></span>
<br />
<span>Account Number:</span><span id="accountNum" data-bind="text: account.accNo"></span>
<br />
<span>Account Type:</span><span id="accountType" data-bind="text: account.type"></span>
<br />
<span>Status:</span><span id="accountStatus" data-bind="text: account.status"></span>
效果如下:
这时候我们的UI绑定的是数据对象的某个属性,但是看起来优势不是很明显。看下面的例子!
3.数据改变的绑定
<script type="text/javascript">
$(document).ready(function () {
function Account(bank, accNo, type, status) {
var self = this;
self.bank = bank;
self.accNo = accNo;
self.type = type;
self.status = ko.observable(status);
};
function AccountViewModel() {
var self = this;
self.account = new Account("sbi",
"12345678", "Saving", "Active");
};
ko.applyBindings(new AccountViewModel());
});
</script>
<h2>My Account </h2>
<span>Bank Name:</span>
<span data-bind="text: account.bank"
span id="accontBankName"></span>
<br />
<span>Account Number:</span>
<span data-bind="text: account.accNo"
span id="accountNum"></span>
<br />
<span>Account Type:</span>
<span data-bind="text: account.type"
span id="accountType"></span>
<br />
<span>Status:</span>
<span data-bind="text: account.status"
span id="accountStatus"></span>
<p>
Change Account status
<input data-bind="value:account.status" />
</p>
效果如下:
这时候我们修改文本框里面的Active值,我们发现状态随之改变!
我们改变文本框的时候,knockout 帮我们去修改了对象的值;那么KNOCKOUT只能做这些吗?显然不是这样的!
4.动态计算
<script type="text/javascript">
$(document).ready(function() {
// Here's my data model
// Here's my data model
var ViewModel = function (first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);
this.fullName = ko.pureComputed(function () {
// Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
return this.firstName() + " " + this.lastName();
}, this);
};
ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work
});
</script>
<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>
上面输入的值能够立即通过计算显示到下面。
注意:
开发环境VS2013 + KNOCKOUT3 + CHROME
源代码下载:http://download.csdn.net/detail/afandaafandaafanda/8544045