3.依赖跟踪如何工作

初学者不需要知道这一点,但更高级的开发人员将想知道为我们怎么实现KO自动跟踪依赖性和自动更新UI的正确部分...

它其实相当简单优雅,跟踪算法如下:

  1. 当你定义一个计算监控,KO立即调用其求值函数来获得初始值。
  2. 当求值函数运行,KO添加一个订阅到任何求值函数可读取的监控对象上(包括其他计算监控对象)。订阅的回调函数会触发求值函数重新运行,整个过程循环回到步骤1(释放任何不再使用的旧订阅)。
  3. KO通知任何订阅者获取你的计算监控的新值。

因此,KO不只是在第一次求值程序运行的时候检测依赖关系,每次都会重新检测。这意味着,例如,依赖关系可以动态变化:依赖A可以决定是否计算监控也取决于B或C,那么,它只会重新求值,无论是A或你目前选择的B或C发生变化。您不必声明依赖项:它们在代码执行的运行时中确定。

另一个诀窍是声明性绑定可以看做是计算监控的简单实现。因此,如果一个绑定读取一个监控的值,绑定会依赖于监控,这将导致如果监控发生变化,绑定会重新求值。

1. 使用peek控制依赖

KO的自动依赖跟踪通常如你想要的那样工作。但你可能有时需要确定哪一个监控将导致重新对计算监控求值,特别是如果计算监控执行一些操作,如发送一个Ajax请求。peek函数可以让你访问一个监控或计算监控的值,而不会创建一个依赖。

在下面的例子里,一个计算监控用来重载一个叫做currentPageData的监控对象的值,该计算监控使用Ajax和来自其他两个监控属性的数据进行请求。每当pageIndex的值发生改变时,计算监控会重新求值,但是会忽略selectedItem的改变,因为是使用peek进行访问的。在这种情况下,用户可能想要使用selectedItem当前的值仅用于跟踪当新的数据集加载的时候。

ko.computed(function() {
var params = {
page: this.pageIndex(),
selected: this.selectedItem.peek()
};
$.getJSON('/Some/Json/Service', params, this.currentPageData);
}, this);

注意:如果你想阻止计算监控频繁刷新,请使用频率限制扩展器。

2. 忽略计算中的依赖关系

ko.ignoreDependencies函数适用于如下场景,在你想执行一个计算代码,而计算监控不会重新求值。这在自定义绑定的情况下特别有用,当你想调用的代码可能会访问监控对象,但是你不想再触发基于这些监控对象的值更新。

ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

例如:

ko.bindingHandlers.myBinding = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = ko.unwrap(valueAccessor());
var value = ko.unwrap(options.value);
var afterUpdateHandler = options.afterUpdate; // the developer supplied a function to call when this binding updates, but
// we don't really want to track any dependencies that would re-trigger this binding
if (typeof afterUpdateHandler === "function") {
ko.ignoreDependencies(afterUpdateHandler, viewModel, [value, color]);
} $(element).somePlugin("value", value);
}
}

注意:为什么循环依赖是没有意义的

计算监控被用于映射一组监控对象的输入值进行计算,返回值作为一个简单监控对象的输出。因此,在你的依赖链中循环依赖是没有意义的。循环依赖不同于递归;它类似于两个电子表格单元互相计算对方的值。这会导致一个死循环。

那么,如果你在你的依赖关系图中有一个循环依赖,KO会做什么?它通过执行以下规则避免了无限循环:KO不会在一个计算监控已经在求值的情况下重新求值。这个不可能影响到你的代码。它跟两种情况有关联:当两个计算监控互相依赖(可能有人个使用deferevaluation选项),或者当一个计算监控把值写入另一个有依赖的监控对象(无论是直接依赖或通过依赖链)。如果你想要使用其中某个方式,而且想完全避免循环依赖,你可以使用如上所述的peek函数。

Knockout v3.4.0 中文版教程-7-计算监控-依赖跟踪如何工作的更多相关文章

  1. Knockout v3.4.0 中文版教程-6-计算监控-可写的计算监控

    2.可写的计算监控 初学者可能想要跳过本节 - 可写的计算监控是相当高级的部分,在大多数情况下不是必需的. 通常,计算监控是一个通过其他监控值计算出的值,因此是只读的. 令人惊讶的是,可以使计算监控值 ...

  2. Knockout v3.4.0 中文版教程-8-计算监控-纯计算属性

    4.纯计算属性 纯计算监控在KO 3.2.0中开始引入,比大多数应用程序使计算监控有更大的性能提升和内存优化.这是因为在自身没有订阅的时候不会保持订阅状态.特性如下 阻止内存泄露 - 避免在应用程序里 ...

  3. Knockout v3.4.0 中文版教程-5-计算监控-使用计算监控

    3. 计算监控 1.使用计算监控 如果你有一个监控的属性firstName和另一个lastName,但你想显示全名怎么办? 这就是引入计算监控的原因-这是依赖于一个或多个其他的observables函 ...

  4. Knockout v3.4.0 中文版教程-9-计算监控-API参考

    5.参考 下面的内容描述了如何构建和使用计算监控. 1. 构建一个计算监控 可以用如下的形式构建一个计算监控: ko.computed( evaluator [, targetObject, opti ...

  5. Knockout v3.4.0 中文版教程-4-通过监控数组工作

    2.通过监控数组工作 1. 监控数组 如果你想检测或者响应一个对象的改变,你用observables.如果你想检测和响应一个集合的改变,使用observableArray.这个在很多情况下都非常有用, ...

  6. Knockout v3.4.0 中文版教程-16-控制流-foreach绑定

    2. 控制流 1. foreach绑定 目的 foreach绑定会遍历一个数组,为每个数组项生成重复的元素标记结构并做关联.这在渲染列表或表格的时候特别有用. 假设你的数组是一个监控数组,之后无论你进 ...

  7. Knockout v3.4.0 中文版教程-1-入门和安装

    英文原版教程:http://knockoutjs.com/documentation/introduction.html 注:此教程根据英文原版翻译,仅作练习,如有不足或错误,请指正 说明: 对原文中 ...

  8. Knockout v3.4.0 中文版教程-11-控制文本内容和外观-text绑定

    2. text绑定 目的 text绑定把传入的参数通过关联的DOM元素来显示文本值. 通常这对像<span>或<em>标签等使用,但技术上你可以对任何元素使用该绑定. 例子 T ...

  9. Knockout v3.4.0 中文版教程-2-监控-通过监控创建视图模型(上)

    2. 监控 1.通过监控创建视图模型 1. 监控 Knockout是基于以下三个核心特性: 监控和依赖跟踪 声明式绑定 模板 在本节,你将第一次了解这三个特性,在这之前,我们先来了解以下MVVM模式和 ...

随机推荐

  1. 092 Reverse Linked List II 反转链表 II

    反转从位置 m 到 n 的链表.用一次遍历在原地完成反转.例如:给定 1->2->3->4->5->NULL, m = 2 和 n = 4,返回 1->4-> ...

  2. [已读]用Angularjs开发下一代web应用

    屯了很久了,貌似是国内出现的第一本讲angularjs的书...上上周看完的时候,angular2都要出来了...angular的双向绑定很赞,因为之前公司后台系统我都用tmodjs做,模板语法什么的 ...

  3. QQ免费企业邮箱申请配置

    对于小企业来说,免费的企业邮箱是不错的选择,省去服务器费用和人员维护费用.在这里说一下,qq的免费企业邮箱.如果想搭建自己的企业邮局,请参考:centos extmail postfix nginx ...

  4. WPF中获取指定坐标依赖对象数据项

    上图中红色框区域是一个自定义的ListBox控件,需要实现的功能是,点击红框区域中某项时,获取当前选中项的数据项 控件的MouseDown事件部分代码为: var x = TreeHelper.Fin ...

  5. vs 2017注册码 激活码

    Visual Studio 2017(VS2017) 企业版 Enterprise 注册码:NJVYC-BMHX2-G77MM-4XJMR-6Q8QFVisual Studio 2017(VS2017 ...

  6. Azure 项目构建 – 构建稳定的直播和点播教学系统

    本课程主要介绍了如何在 Azure 平台上快速构建和部署基于 Azure 虚拟机的点播和直播教学系统, 实践讲解如何使用 Azure 门户创建虚拟机,配置视频服务,连接 CDN 加速 等. 具体包括项 ...

  7. Redis监控之redis-live.conf配置

    { "RedisServers": [ { "server": "192.168.1.201", "port": 637 ...

  8. Servlet和JSP之标签文件学习

    在上一篇文章中介绍了自定义标签的用法,接下来介绍标签文件的用法啦. tag file指令 tag file简介 用tag file的方式,无需编写标签处理类和标签库描述文件,也可以自定义标签.tag ...

  9. Kubenetes里pod和service绑定的实现方式

    我之前的文章 如何在Kubernetes里创建一个Nginx service介绍了如何创建一个Kubernetes pod和service,使用的方法是命令kubectl run. 本文介绍另一种方式 ...

  10. Integer比较浅析

    //Integer 型比较假如是使用 == ,只能比较数值为-128~127数值; 在这个范围内使用的是自动装箱拆箱: //.intValue()使用这个需要确认属性不为null; //equals( ...