Knockout observables提供了支持读取/写入值并在值改变时通知订阅者所需的基本功能。 但在某些情况下,您可能希望向可观察者添加其他功能。 这可能包括通过在可观察者前面放置一个可写的计算可观察符来向可观察或截取写入添加额外的属性。 敲除扩展器提供了一种简单和灵活的方式来对可观察者进行这种类型的扩充。

如何创建扩展器

创建扩展器涉及向ko.extenders对象添加一个函数。 函数接受observable本身作为第一个参数和第二个参数中的任何选项。 然后它可以返回observable或返回一些新的像一个计算的observable,它以某种方式使用原来的observable。

这个简单的logChange扩展器订阅了observable,并使用控制台写入任何更改以及可配置的消息。

ko.extenders.logChange = function(target, option) {
target.subscribe(function(newValue) {
console.log(option + ": " + newValue);
});
return target;
};

您将通过调用observable的extend函数并传递包含日志Change属性的对象来使用此扩展器。

this.firstName = ko.observable("Bob").extend({logChange: "first name"});

如果firstName observable值更改为Ted,那么控制台将显示名字:Ted。

示例1:强制输入为数字

此示例创建一个扩展器,该扩展器强制对可观察对象的写入被四舍五入到可配置的精度级别。 在这种情况下,扩展器将返回一个新的可写的计算可观察,它将位于真正的可观察的拦截写入之前。

(round to whole number)

(round to two decimals)

UI源码:

<p><input data-bind="value: myNumberOne" /> (round to whole number)</p>
<p><input data-bind="value: myNumberTwo" /> (round to two decimals)</p>

视图模型源码:

ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier; //only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({ notify: 'always' }); //initialize with current value to make sure it is rounded appropriately
result(target()); //return the new computed observable
return result;
}; function AppViewModel(one, two) {
this.myNumberOne = ko.observable(one).extend({ numeric: 0 });
this.myNumberTwo = ko.observable(two).extend({ numeric: 2 });
} ko.applyBindings(new AppViewModel(221.2234, 123.4525));

注意,为了自动从UI中删除被拒绝的值,有必要在计算的observable上使用.extend({notify:'always'})。 没有这个,用户可能输入一个无效的newValue,当四舍五入得到一个不变的valueToWrite。 然后,由于模型值不会改变,因此在UI中没有更新文本框的通知。 使用{notify:'always'}会导致文本框刷新(删除被拒绝的值),即使计算的属性没有更改值。

示例2:向可观察者添加验证

此示例创建一个扩展器,允许将observable标记为必需。 这个扩展器不是返回一个新的对象,而是简单地向现有的observable添加额外的子可观察量。 因为observables是函数,它们实际上可以有自己的属性。 但是,当视图模型转换为JSON时,子可观察项将被删除,我们将只剩下我们的实际observable的值。 这是一个很好的方法来添加只与UI相关的附加功能,而不需要发送回服务器。

UI源码:

<p data-bind="css: { error: firstName.hasError }">
<input data-bind='value: firstName, valueUpdate: "afterkeydown"' />
<span data-bind='visible: firstName.hasError, text: firstName.validationMessage'> </span>
</p>
<p data-bind="css: { error: lastName.hasError }">
<input data-bind='value: lastName, valueUpdate: "afterkeydown"' />
<span data-bind='visible: lastName.hasError, text: lastName.validationMessage'> </span>
</p>

视图模型晕吗:

ko.extenders.required = function(target, overrideMessage) {
//add some sub-observables to our observable
target.hasError = ko.observable();
target.validationMessage = ko.observable(); //define a function to do validation
function validate(newValue) {
target.hasError(newValue ? false : true);
target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
} //initial validation
validate(target()); //validate whenever the value changes
target.subscribe(validate); //return the original observable
return target;
}; function AppViewModel(first, last) {
this.firstName = ko.observable(first).extend({ required: "Please enter a first name" });
this.lastName = ko.observable(last).extend({ required: "" });
} ko.applyBindings(new AppViewModel("Bob","Smith"));

应用多个扩展程序

多个扩展器可以在对可观察者的.extended方法的单个调用中应用。

this.firstName = ko.observable(first).extend({ required: "Please enter a first name", logChange: "first name" });

在这种情况下,required和logChange扩展器都会对我们的observable执行。

KnockoutJS 3.X API 第七章 其他技术(2) 使用扩展器来增加可观察量(监控属性)的更多相关文章

  1. KnockoutJS 3.X API 第七章 其他技术(4) 速率限制

    注意:这个速率限制API是在Knockout 3.1.0中添加的. 通常,更改的observable立即通知其订户,以便依赖于observable的任何计算的observable或绑定都会同步更新. ...

  2. KnockoutJS 3.X API 第七章 其他技术(8) 异步错误处理

    注意:本文档适用于Knockout 3.4.0及更高版本. ko.onError Knockout包装内部异步调用,并在抛出原始错误之前查找可选的ko.onError回调以执行(如果遇到异常). 这使 ...

  3. KnockoutJS 3.X API 第七章 其他技术(7) 微任务

    注意:本文档适用于Knockout 3.4.0及更高版本. Knockout的微任务队列 Knockout的微任务队列支持调度任务尽可能快地运行,同时仍然是异步的,努力安排它们在发生I / O,回流或 ...

  4. KnockoutJS 3.X API 第七章 其他技术(6) 使用“fn”添加自定义函数

    有时,您可能会通过向Knockout的核心值类型添加新功能来寻找机会来简化您的代码. 您可以在以下任何类型中定义自定义函数: 因为继承,如果你附加一个函数到ko.subscribable,它将可用于所 ...

  5. KnockoutJS 3.X API 第七章 其他技术(5) 使用其他事件处理程序

    在大多数情况下,数据绑定属性提供了一种干净和简洁的方式来绑定到视图模型. 然而,事件处理是一个常常会导致详细数据绑定属性的领域,因为匿名函数通常是传递参数的推荐技术. 例如: <a href=& ...

  6. KnockoutJS 3.X API 第七章 其他技术(3) 延迟更新

    .example { display: inline-block; padding: 1em; margin-right: 2em; background: #F6F6EF; } 注意:本文档适用于K ...

  7. KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据

    Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...

  8. KnockoutJS 3.X API 第六章 组件(3) 组件绑定

    组件绑定将指定的组件注入到元素中,并且可选地将参数传递给它. 本节目录 一个例子 API 组件生命周期 备注1:仅限模板组件 备注2:使用没有容器元素的组件 备注3:将标记传递给组件 处置和内存管理 ...

  9. KnockoutJS 3.X API 第三章 计算监控属性(1) 使用计算监控属性

    计算监控属性(Computed Observables) 如果你有一个监控属性firstName,和另一个lastName,你要显示的全名?可以使用计算监控属性来实现-它依赖于一个或多个其他监控属性, ...

随机推荐

  1. 【签名之坑】Decmail.GetBits()

    decimal类型有GetBits()方法 可以获取到值的int[4]值,进而获取到byte[16]值 在c#里,0m和0.00m获取到的byte[]是不一样的(具体为何不一样,自己百度) 在sql里 ...

  2. Angular 单元格合并

    在Angular实现表格输出的话,使用ng-repeat输出信息, 使用了: ng-repeat-start ng-repeat-end ng-hide="$first" < ...

  3. MSSQL数据库表加锁

    所指定的表级锁定提示有如下几种: 1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁. 2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可 ...

  4. 浏览器的兼容问题 判断IE方法

    下面是一些判断ie的常用方法: <!-[if IE 6]> 此处是IE6才会执行的代码 <![endif]-> 还可以给他加个条件,比如判断IE6以下的浏览器: <!-[ ...

  5. 如何对tableview进行自定义多选

    前言: 很多入门不久的程序员或许都会遇到系统自带的tableview多选时cell选择时不能选择自己想要的点击时的颜色或者图片,这让初级开发者们很烦恼.今天,我试着花了几个小时的时间用了自己的想法,去 ...

  6. java 过滤表情符号

    /** * 过滤表情符号 * @create by ldw on 2016-10-25 * @param str * @return str(去掉表情符号的字符串) * @version 1.0 * ...

  7. 理解PagerAdapter的instantiateItem()方法

    在为ViewPager设置Adapter时肯定会用到PagerAdapter,Google Android文档对该类的定义如下: Base class providing the adapter to ...

  8. 浅谈数据库优化方案--表和SQL

    1.数据类型的选择 1.字段最好设置为非空.若字段为char(8),即便是NULL也会现有8个字符的空间. 2.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能, ...

  9. 验证mongodb副本集并实现自动切换primary~记录过程

    接 验证mongodb主从复制过程 1.创建数据目录 同 验证mongodb主从复制过程 的实验一样,本次实验也是采用直接指定启动参数来启动mongodb数据库,本次实验我们需要启动三个数据库,为了与 ...

  10. photoshop

    photoshop裁剪 photoshop裁剪快捷键是C键: 使用photoshop裁剪工具裁切出图片的方法: 选择好所需要的图片,右键保存到本地计算机' 在photoshop中打开这张图片(文件/打 ...