可写的计算监控(Writable computed observables)
新手可忽略此小节,可写依赖监控属性真的是太advanced了,而且大部分情况下都用不到。
一般情况下,计算监控的值是通过其他监控属性的值计算出来的,因此它是只读的。这个看似很奇怪,我们有什么办法可以让他变成可写的吗。 此时,我们只需要提供一个callback的函数就可以做到。
通过你自定义的逻辑拦所有的读写操作,你可以像使用其他监控属性一样使用计算监控属性。类似obeservables一样,你可以一次改变多个observable或者computered observable属性的值,通过以下这种方式:
myViewModel.fullName('Joe Smith').age(50).
可写的计算监控属性在某些场景下将会是一个非常有用的特性。
示例1:分解用户输入
返回到经典的“first name + last name = full name” 例子上,你可以让事情调回来看: 让依赖监控属性fullName可写,让用户直接输入姓名全称,然后输入的值将被解析并映射写入到基本的监控属性firstName和lastName上:
<div>First name: <span data-bind="text: firstName"></span></div>
<div>Last name: <span data-bind="text: lastName"></span></div>
<div class="heading">Hello, <input data-bind="textInput: fullName"/></div>
function MyViewModel() {
this.firstName = ko.observable('Planet');
this.lastName = ko.observable('Earth');
this.fullName = ko.pureComputed({
read: function () {
return this.firstName() + " " + this.lastName();
},
write: function (value) {
var lastSpacePos = 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());
这是一个Hello World 例子的反例子,姓和名都不可编辑,相反姓和名组成的姓名全称却是可编辑的。
上面的view model演示的是通过一个简单的参数来初始化计算监控属性(computed observables)。详细的参数说明请参见computed observable reference。
示例2:全选/反选所有项
当呈现给用户一系列可选择的项时,我们通常会提供全选和反选的功能。这时,可以使用一个bool值来比较直观的表示是否是全选或者是反选。当返回True时表示选择了所有项,当返回false时表示反选。

HTML:
<div class="heading">
<input type="checkbox" data-bind="checked: selectedAllProduce" title="Select all/none"/> Produce
</div>
<div data-bind="foreach: produce">
<label>
<input type="checkbox" data-bind="checkedValue: $data, checked: $parent.selectedProduce"/>
<span data-bind="text: $data"></span>
</label>
</div>
view model:
function MyViewModel() {
this.produce = [ 'Apple', 'Banana', 'Celery', 'Corn', 'Orange', 'Spinach' ];
this.selectedProduce = ko.observableArray([ 'Corn', 'Orange' ]);
this.selectedAllProduce = ko.pureComputed({
read: function () {
// Comparing length is quick and is accurate if only items from the
// main array are added to the selected array.
return this.selectedProduce().length === this.produce.length;
},
write: function (value) {
this.selectedProduce(value ? this.produce.slice(0) : []);
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
示例3:value转换器
有时候你可能需要显示一些不同格式的数据,从基础的数据转化成显示格式。比如,你存储价格为float类型,但是允许用户编辑的字段需要支持货币单位和小数点。你可以用可写的计算监控属性来实现,然后解析传入的数据到基本 float类型里:
HTML:
<div>Enter bid price: <input data-bind="textInput: formattedPrice"/></div>
<div>(Raw value: <span data-bind="text: price"></span>)</div>
view model:
function MyViewModel() {
this.price = ko.observable(25.99);
this.formattedPrice = ko.pureComputed({
read: function () {
return '$' + this.price().toFixed(2);
},
write: function (value) {
// Strip out unwanted characters, parse as float, then write the
// raw data back to the underlying "price" observable
value = parseFloat(value.replace(/[^\.\d]/g, ""));
this.price(isNaN(value) ? 0 : value); // Write to underlying storage
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
这样,当用户输入一个新的价格时,无论用户输入的是什么格式,text box就会将会将它格式化成货币符号并且只有两位小数。这样的用户体验就比较好。当用户输入了超过两位小数的数据时,系统就会自动舍弃多余的小数,只保留两位,然后用户就会知道不可以输入超过两位小数的值。同样,也不可以输入负数,因为系统会自动把负号去掉。
示例4:过滤并验证用户的输入
例1展示的是写操作过滤的功能,如果你写的值不符合条件的话将不会被写入,忽略所有不包括空格的值。
再多走一步,你可以声明一个监控属性isValid 来表示最后一次写入是否合法,然后根据真假值显示相应的提示信息。其他还有更简单的方法来做全法性验证(后面再介绍),先看下面的示例:
HTML:
<div>Enter a numeric value: <input data-bind="textInput: attemptedValue"/></div>
<div class="error" data-bind="visible: !lastInputWasValid()">That's not a number!</div>
<div>(Accepted value: <span data-bind="text: acceptedNumericValue"></span>)</div>
View Model:
function MyViewModel() {
this.acceptedNumericValue = ko.observable(123);
this.lastInputWasValid = ko.observable(true);
this.attemptedValue = ko.pureComputed({
read: this.acceptedNumericValue,
write: function (value) {
if (isNaN(value))
this.lastInputWasValid(false);
else {
this.lastInputWasValid(true);
this.acceptedNumericValue(value); // Write to underlying storage
}
},
owner: this
});
}
ko.applyBindings(new MyViewModel());
现在,acceptedNumericValue 将只接受数字,其它任何输入的值都会触发显示验证信息,而会更新acceptedNumericValue。
备注:上面的例子显得杀伤力太强了,更简单的方式是在<input>上使用jQuery Validation和number class。Knockout可以和jQuery Validation一起很好的使用,参考例子:grid editor。当然,上面的例子依然展示了一个如何使用自定义逻辑进行过滤和验证数据,如果验证很复杂而jQuery Validation很难使用的话,你就可以用它。
可写的计算监控(Writable computed observables)的更多相关文章
- Knockout v3.4.0 中文版教程-6-计算监控-可写的计算监控
2.可写的计算监控 初学者可能想要跳过本节 - 可写的计算监控是相当高级的部分,在大多数情况下不是必需的. 通常,计算监控是一个通过其他监控值计算出的值,因此是只读的. 令人惊讶的是,可以使计算监控值 ...
- 使用计算监控(Using computed observables)
计算监控(Computed Observables) 如果有两个监控属性firstName, lastName,此时我们要显示full name,我们要怎么办呢? 这时,可以创建一个computed ...
- KnockoutJS 3.X API 第三章 计算监控属性(1) 使用计算监控属性
计算监控属性(Computed Observables) 如果你有一个监控属性firstName,和另一个lastName,你要显示的全名?可以使用计算监控属性来实现-它依赖于一个或多个其他监控属性, ...
- Knockout 新版应用开发教程之Computed Observables
Computed Observables 如果你有监控属性firstName和lastName的话,此时如果你想要显示全名? 这个时候computed(以前叫做依赖)监控属性就出马了,这是一个函数用来 ...
- KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
Pure computed observables Pure computed observables是KO在3.2.0版本中推出的.她相对于之前的ComputedObservables有很多改进: ...
- 纯计算监控(Pure computed observables)
纯计算监控,在knockout 3.2.0里才有,提供了对性能和内存更好的管理.这是因为纯计算监控不包含对他的依赖的订阅.特点有: 防止内存泄漏 降低计算开销:值不再是observed,是一个不会重新 ...
- KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
计算监控属性构造参考 计算监控属性可使用以下形式进行构造: ko.computed( evaluator [, targetObject, options] ) - 这种形式是创建一个计算监控属性最常 ...
- Knockout v3.4.0 中文版教程-5-计算监控-使用计算监控
3. 计算监控 1.使用计算监控 如果你有一个监控的属性firstName和另一个lastName,但你想显示全名怎么办? 这就是引入计算监控的原因-这是依赖于一个或多个其他的observables函 ...
- KnockoutJS 3.X API 第三章 计算监控属性(2) 可赋值的计算监控属性
.liveexample{ padding: 1em; background-color: #eeeedd; border: 1px solid #ccc; max-width: 655px; fon ...
随机推荐
- Mediawiki随笔
http://www.ibm.com/developerworks/cn/opensource/os-mediawiki/ 定制wiki http://www.zzbaike.com/wiki/Me ...
- cursor属性
cursor光标类型 auto default none context-menu help pointer progress wait cell crosshair text vertical-te ...
- Ubuntu 14.04 配置FTP
配置Ubuntu 14.04的FTP服务,通过Windows远程访问Ubuntu 14.04的同时,可以实现windows和Ubuntu之间的文件交换传输.在多用户环境下,每一个用户都可以通过自己的帐 ...
- spring定时任务的几种实现方式
Spring定时任务的几种实现 近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将 ...
- checkbox批量操作
hang=data.split("\1");//获取 查询返回的数据 处理数据 var str=""; for(var i =0;i<hang.lengt ...
- openvpn环境搭建
以下为服务端.客户端下载安装包,在CentOS 6.5部署,也可以找到相关下载源 openvpn-2.2.2.tar.gz,openvpn-2.1.3-install.rar,(https://git ...
- Android:关于背景选择器Selector的item顺序
在使用背景选择器的时候,如果item的顺序不对,会导致不起作用. 1.首先背景选择器的normal选项一定要放在最后. 2.pressed的选择器应该在seclet的前面.我在使用的时候找了半天问题, ...
- lldb 命令
po [[UIWindow keyWindow] recursiveDescription]
- Mybatis的失误填坑-java.lang.Integer cannot be cast to java.lang.String
Mybatis的CRUD小Demo 为方便查看每次的增删改结果,封装了查询,用来显示数据库的记录: public static void showInfo(){ SqlSession session ...
- linux的命令使用记录
iptables禁止53端口的出包(dns) iptables -A OUTPUT -p udp --dport 53 -j DROP linux查看网络监听端口 netstat -npl 文件复制 ...