Knockout初体验--监控属性

  Knockout是一款很优秀的JavaScript库(简称KO),它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的用户界面。任何时候你的局部UI内容需要自动更新(比如:依赖于用户行为的改变或者外部的数据源发生变化),KO都可以很简单的帮你实现,并且非常易于维护。

  Knockout有以下几个重要概念

声明式绑定(Declarative Bindings):使用简明易读的语法很容易地将模型(model)数据关联到DOM元素上。

UI界面自动刷新(Automatic UI Refresh):当您的模型状态(model state)改变时,您的UI界面将自动更新。

依赖跟踪(Dependency Tracking):为转变和联合数据,在你的模型数据之间隐式建立关系。

模板(Templating):为您的模型数据快速编写复杂的可嵌套的UI。

下载安装
  Knockout的核心类库是纯JavaScript代码实现的,不依赖任何其他类库,所以按照如下步骤即将KO添加到你的项目里:

  下载Knockout的最新版本,下载地址: http://knockoutjs.com/downloads/index.html

  在你的HTML页面中通过< script >标签引用Knockout文件。

这里写代码
<script src="knockout-3.4.0.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
    <title>konckout学习系列</title>
    <script src="lib/knockout-3.4.0.js"></script>
</head>
<body>
    输入值:<input type="text" id="txtValue" data-bind="value: personName" /><br/>
    响应文本:<span id="spnValue" data-bind="text: personName"></span>
</body>
</html>

可以看到,我们几乎都没写什么,完成了自动的感应和数据的绑定。

  1.只定义了一个 myViewModel组件对象(包含一个myValue的属性)。

  2.通过data-bind=”value: myValue”将myValue属性绑到的value值。

  3.通过data-bind=”text: myValue”将属性值动态的反映到中。

  4.添加ko.applyBindings( )绑定。

  
  注意:KO的绑定都是通过data-bind属性进行绑定的。

View Models
  Knockout是在下面三个核心功能是建立起来的:

  监控属性(Observables)和依赖跟踪(Dependency tracking)、声明式绑定(Declarative bindings)、模板(Templating)。

  在这一章中我们先介绍3个功能中的第一个。 在这之前, 我们来解释一下MVVM模式和view model的概念。

  Model-View-View Model (MVVM) 是一种创建用户界面的设计模式。 描述的是如何将复杂的UI用户界面分成3个部分:

  model: 你程序里存储的数据。这个数据包括对象和业务操作(例如:银子账户可以完成转账功能), 并且独立于任何UI。使用KO的时候,通常说是向服务器调用Ajax读写这个存储的模型数据。

  view model: 在UI上,纯code描述的数据以及操作。例如,如果你实现列表编辑,你的view model应该是一个包含列表项items的对象和暴露的add/remove列表项(item)的操作方法。

  view: 一个可见的,交互式的,表示view model状态的UI。 从view model显示数据,发送命令到view model(例如:当用户click按钮的时候) ,任何view model状态改变的时候更新。

  使用KO时,你的View层主要就是简单的将HTML文档声明式的绑定到View Model,将它们关联起来。使用KO创建一个View Model,仅仅只需要声明一个JavaScript对象,例如:

var myViewModel = {personName: ‘Bob’,personAge: 123};
然后就可以为view model创建一个声明式绑定的简单view。例如:下面的代码显示personName 值:

The name is <span data-bind="text: personName"></span>

最后激活Knockout,只需要将下面的代码加到<script>标签中就可以了:

ko.applyBindings(myViewModel);

Observables
  KO一个重要的功能是当你的view model改变的时候能自动更新你的界面。当你的view model部分改变的时候KO是如何知道的呢?答案是:你需要将你的model属性声明成observable的, 因为它是非常特殊的JavaScript对象,能够通知订阅者它的改变以及自动探测到相关的依赖。

 var myViewModel = {
    personName: ko.observable('Bob'),
    personAge: ko.observable(123)
};

注:Bob作为persionName 的默认值。

  你根本不需要修改view– 所有的data-bind语法依然工作,不同的是他能监控到变化,当值改变时,view会自动更新。

  读取监控属性的值,只需要直接调用监控属性(不需要参数),例如:

myViewModel.personName(); //将返回'Bob', 
myViewModel.personAge();  //将返回 123

  写一个新值到监控属性上,调用这个observable属性并当新值作为参数。例如:

myViewModel.personName(‘Mary’); //将更新name值为’Mary’。

observableArray
  如果我们需要探测和响应一个集合对象的变化,就应该用observableArray。在很多场景下,它都非常有用,比如要在UI上需要显示/编辑的一个列表数据集合,然后对集合进行添加和删除。

var myObservableArray = ko.observableArray(); // 初始化一个空数组
myObservableArray.push(‘Some value’); // 向数组中添加数据
当然也可以在初始化时对数组赋值:

var anotherObservableArray = ko.observableArray([
{ name: “Bungle”, type: “Bear” },
{ name: “George”, type: “Hippo” },
{ name: “Zippy”, type: “Unknown” }
]);
  我们可以像获取普通的observable的值一样,只需要调用无参函数就可以获取自身的值了。 例如,

alert(‘The array length is ’ + myObservableArray().length); //数组的长度
alert(‘The first element is ’ + myObservableArray()[0]); //数组的第一个元素
  另外KO也提供了一些操作数组的方法:

  myObservableArray.push(‘Some new value’) 在数组末尾添加一个新项;

  myObservableArray.pop() 删除数组最后一个项并返回该项;

  myObservableArray.unshift(‘Some new value’) 在数组头部添加一个项;

  myObservableArray.shift() 删除数组头部第一项并返回该项;

  myObservableArray.reverse() 翻转整个数组的顺序;

  myObservableArray.sort() 给数组排序,等等。

ko.computed
  如果你已经有了一个监控属性firstName和lastName,如果你想显示全名该怎么做呢?这个时候就可以通过计算属性(ko.computed)来实现,这个方法依赖于一个或多个监控属性,如果任何依赖对象发生改变他们就会跟着改变。如下代码:

function AppViewModel(){
this.firstName=ko.observable(‘Bob’);
this.lastName=ko.observable(‘Smith’);
}
下面添加一个计算属性来返回全名,例如:

function AppViewModel(){
// … leave firstName and lastName unchanged …
this.fullName=ko.computed(function(){
return this.firstName()+” “+this.lastName();
},this);}
下面就可以将它绑定到UI对象上了,如:

The name is <span data-bind="text: fullName"></span>
  当firstName或者lastName变化,它将会随时更新(当依赖关系发生变化,你的计算函数就会被调用,并且它的值都会更新到UI对象或其他的依赖属性上去)。

你可能想知道ko.computed的第二个参数是什么(前面的代码中我们使用到了this),当依赖属性定义了this的值,没有传递它进去,你不可能得到this.firstName()或者this.lastName()。有经验的JavaScript开发人员觉得this没什么的,但如果你不熟悉JavaScript,你就会觉得这样写很奇怪。(像C#和Java这类语言不需要开发人员给this赋值,但JavaScript需要,因为在默认情况下,它的函数本身并不是任何对象的一部分)。

  以上计算属性方法还可以简化为:

function AppViewModel(){
var self=this;
self.firstName=ko.observable(‘Bob’);
self.lastName=ko.observable(‘Smith’);
self.fullName=ko.computed(function(){
return self.firstName()+” “+self.lastName();
});
}
  由于self在闭合的方法内部也是可以捕获到的,所以在任何嵌套函数当中,它仍然可用并保持一致性。

可写的计算属性
  计算属性是通过计算其他监控属性而得到的一个值。从这个意义上说,计算属性通常情况下是只读的,你可能会比较惊讶,怎么可能让计算属性变的可写。你仅仅只需要提供一个回调函数来实现值的写入。

function MyViewModel() {
this.firstName = ko.observable(‘Bob’);
this.lastName = ko.observable(‘Smith’);
this.fullName = ko.computed({
read: function () { },
write: function (value) {
varlastSpacePos = value.lastIndexOf(” “);
if (lastSpacePos > 0) {
// Ignore values with no space character
this.firstName(value.substring(0, lastSpacePos));
// Update “firstName”
this.lastName(value.substring(lastSpacePos + 1));
// Update “lastName”
}
}, owner: this
});
}
ko.applyBindings(new MyViewModel());
  在这个例子当中,write回调事件来处理用户输入的值将其分解成“firstName”和“lastName”两个部分,并将这些值返回到底层监控属性上。

工作方式
依赖跟踪是如何工作的呢?事实上它是很简单的,跟踪算法是这样的:

当你声明一个依赖属性时,KO会立即调用求值算法得到其初始值;
当你的计算函数运行的时候,KO会把监控属性通过计算得到的值都记录在一个Log中;
当你的计算结束的时候,KO会订阅能够访问的监控属性或依赖属性,订阅的回调函数是重新运行你的计算函数,循环整个过程,回到步骤1(并且注销不再使用的订阅);
KO会通知所有的订阅者,你的依赖属性已经被设置了新值。
  所以说,KO并不仅仅是在第一次执行计算函数时检测你的依赖项,它每次都会检测。这意味着,你的依赖是可以动态的,举例来说:依赖A能决定你是否也依赖于B或C,这时候只有当A或者你选择的B或者C发生变化时计算函数才能运行。你不需要定义依赖关系:在代码运行时会自动检测到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值