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 observablevar result = ko.pureComputed({read: target,  //always return the original observables valuewrite: 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 changedif (valueToWrite !== current) {target(valueToWrite);} else {//if the rounded value is the same, but a different value was written, force a notification for the current fieldif (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 observablereturn 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 observabletarget.hasError = ko.observable();target.validationMessage = ko.observable();//define a function to do validationfunction 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 observablereturn 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执行。

转载于:https://www.cnblogs.com/smallprogram/p/5976223.html

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

  1. knockoutjs ajax分页,KnockoutJS 3.X API 第四章之数据控制流foreach绑定

    foreach绑定 foreach绑定主要用于循环展示监控数组属性中的每一个元素,一般用于table标签中 假设你有一个监控属性数组,每当您添加,删除或重新排序数组项时,绑定将有效地更新UI的DOM- ...

  2. 交互式计算机图形学总结:第七章 离散技术

    第七章 离散技术 OpenGL缓存 帧缓存的写操作 –写模式(Writing Mode) –位写入模式 –异或写入模式:如果对某一个源位执行两次异或操作,那么返回目标位的初始状态 映射方法 –纹理映射 ...

  3. 软考网络管理员学习笔记7之第七章网络管理技术

    第七章网络管理技术 考点1.Windows的基本管理 [考法分析] 本考点的基本考法是能够识别Windows系统下,常见命令的含义与作用 [要点分析] 1.需要熟悉掌握常见命令,如ipconfig.pi ...

  4. 《自然语言处理(哈工大 关毅 64集视频)》学习笔记:第七章 句法分析技术

    视频列表: 43 句法分析技术(一) 44 句法分析技术(二) 45 句法分析技术(三) 46 句法分析技术(四) 47 句法分析技术(五) 43 句法分析技术(一) 第七章 句法分析技术 什么是句法 ...

  5. KnockoutJS 3.X API 第四章 表单绑定(11) options绑定

    目的 options绑定主要用于下拉列表中(即<select>元素)或多选列表(例如,<select size='6'>).此绑定不能与除<select>元素之外的 ...

  6. KnockoutJS 3.X API 第五章 高级应用(2) 控制后代绑定

    注意:这是一种高级技术,通常仅在创建可重用绑定的库时使用. 默认情况下,绑定仅影响它们应用到的元素. 但是如果你想影响所有的后代元素呢? 为此,只需从绑定的init函数中返回{controlsDesc ...

  7. 【笔记】从 Paxos 到 Zookeeper:第七章 Zookeeper 技术内幕之客户端

    文章目录 系统模型 数据模型 节点特性 版本-保证分布式数据原子性操作 Watcher-数据变更通知 ACL-保障数据安全 序列化与协议 序列化 通信协议 客户端 一次会话的创建过程 初始化阶段 会话 ...

  8. 网络安全技术第七章——防火墙技术概述及应用(包过滤防火墙 、代理防火墙、状态检测防火墙、分布式防火墙)

    防火墙技术概述及应用 防火墙技术概述及应用 1.防火墙的概念 2.高效可靠的防火墙应具备的基本特性 3.防火墙的基本功能 4.防火墙的基本原理 5.防火墙的类型 (1)包过滤防火墙 (2)代理防火墙 ...

  9. 郑捷《机器学习算法原理与编程实践》学习笔记(第七章 预测技术与哲学)7.1 线性系统的预测...

    7.1.1 回归与现代预测 7.1.2 最小二乘法 7.1.3 代码实现 (1)导入数据 def loadDataSet(self,filename): #加载数据集X = [];Y = []fr = ...

最新文章

  1. PyTorch分布式训练
  2. 怎么通过media foundation将图像数据写入虚拟摄像头_不知道怎么挑手机?性价比神机绝对适合你...
  3. SpringBoot中通过重写WebMvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url
  4. Web.config详解
  5. [css] scroll-snap-align属性的应用场景是什么?
  6. MySQL NULL 值处理
  7. socket 选项 详细说明
  8. AT:关闭PSM和EDRX模式
  9. PyTorch学习笔记(七):PyTorch可视化
  10. 2021年58个最佳个人WordPress博客主题
  11. mysql物流管理系统_物流配送中心管理系统(SSM+MYSQL)
  12. MongoDB 数据库简介、安装及使用
  13. win 10 PHP开发环境配置
  14. EB-Boost :智慧景区共享单车中长期投放量精准预测方法
  15. 21世纪 直销势不可挡
  16. 红米9A成功root.9秒解锁BL MIUI12 root权限刷 Magisk面具 TWRP
  17. 跳跃游戏 Jump Game 分析与整理
  18. 来自“飞人”乔丹的启示!奥尼尔开启的另一个“赛场”
  19. 关于新高考中综合素质评价的思考
  20. 文法和语言的基本知识

热门文章

  1. go语言的书籍的淘宝调查
  2. superset可视化-Time-series Percent Change
  3. HDFS/zookeeper/hbase初始化
  4. DataGrip按某列大小对数据集进行排序
  5. keras中的神经网络为什么需要多次epoch
  6. TypeError: 'dict' object is not callable
  7. 计算机系统基础:数字的机器表示
  8. C++PrimerCH2
  9. MobileNet论文阅读笔记
  10. linux创建目录记录日志,创建LVM的日志记录