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. ElasticSearch问题记录

    1.Young GC导致集群master重新选举,一台server fail [2016-12-10 07:38:24,546][WARN ][transport ] [BFRD_1] Receive ...

  2. Day 1:学习Windows Phone 使用 SQLite

    private void move(string fn) { StreamResourceInfo sr = Application.GetResourceStream(new Uri(fn, Uri ...

  3. Android之获取数据库路径

    如果数据库名为:“ifoData.db”,则它的路径求法为 String pathDatabase=Mcontext.getDatabasePath("ifoData.db").g ...

  4. JS 将数字转化成为货币格式

    最近由于项目的需要需要将数字format成货币格式,自己搞了半天效果不是很好,博客园有篇问题很好,再次转载记录一下 http://www.cnblogs.com/mingmingruyuedlut/a ...

  5. java学习-关于字符串String

    有必要总结记录一下java的学习,否则,永远只是记忆碎片化和always google(费时) 刚好,小伙伴给了一份自己做的review,在学习的过程中,update一下自己的见解和学习内容: 关于S ...

  6. 【OAuth2.0】Spring Security OAuth2.0篇之初识

    不吐不快 因为项目需求开始接触OAuth2.0授权协议.断断续续接触了有两周左右的时间.不得不吐槽的,依然是自己的学习习惯问题,总是着急想了解一切,习惯性地钻牛角尖去理解小的细节,而不是从宏观上去掌握 ...

  7. HDU 2202 计算几何

    最大三角形 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  8. jQuery基础的工厂函数以及定时器的经典案例

    1. jQuery的基本信息:  1.1 定义: jQuery是JavaScript的程序库之一,它是JavaScript对象和实用函数的封装, 1.2 作用: 许多使用JavaScript能实现的交 ...

  9. SQL编程篇 (二) 定义与流程控制

    分类: sql编程:标准的sql 编程 * 纯sql 在标准的编程中又分为 sqlserver-->T-sql oracle-->pl-sql(扩展) 变量:在使用变量之前先定义 声明变量 ...

  10. 如何在arcmap中调试addin或者插件

    1. 首先,在arcmap中,依次点击“自定义”->"加载项管理器",加载dll或者tlb文件 2. 其次,在vs中,依次点击“工具”->“附加到进程",在对 ...