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. 17995 Stupid thief 组合数学

    17995 Stupid thief 时间限制:1000MS  内存限制:65535K提交次数:0 通过次数:0 题型: 编程题   语言: 不限定 Description A stupid thie ...

  2. 实现如下语法的功能:var a = (5).plus(3).minus(6);

    Number.prototype.plus= function(val){ return parseInt(this)+val; }; Number.prototype.minus= function ...

  3. Spring Cloud Gateway VS Zuul 比较,怎么选择?

    Spring Cloud Gateway 是 Spring Cloud Finchley 版推出来的新组件,用来代替服务网关:Zuul. 那 Spring Cloud Gateway 和 Zuul 都 ...

  4. centos 7下Hadoop 2.7.2 伪分布式安装

    centos 7 下Hadoop 2.7.2 伪分布式安装,安装jdk,免密匙登录,配置mapreduce,配置YARN.详细步骤如下: 1.0 安装JDK 1.1 查看是否安装了openjdk [l ...

  5. OpenCV中CvMat的初始化[转]

    一)cvCreateMat创建和分配数据CvCreateMat会创建CvMat,并为CvMat分配数据.cvCreateMat可以配合cvInitMatHeader来初始化CvMat对象.因为CvCr ...

  6. Java、Node.js、PHP还是.Net? 无论你选谁,我都能教你一招!

    七夕如期而至,不该来的终究还是来了.再傲娇的单身贵族恐怕也难免在今天会感觉一丝丝的空虚.还好你关注了我,因为接下来我准备了三大招教你一个人…..也可以优雅地过七夕. 招式一:移形幻影,无中生有 七夕当 ...

  7. CentOS7.2+MySQL5.7_ yum源方式_ 安装配置教程

    1)访问mysql官方网站 #访问网站 https://dev.mysql.com/downloads/file/?id=470281 2)下载安装包到linux #进入文件存放路径 cd /usr/ ...

  8. 在Windows 10删除百度云盘的盘符

    1点击微软图标不放,然后点击R  打开运行命令 2输入  Regedit  进入注册表 3找到以下路径:HKEY_LOCAL_MACHINE  SOFTWARE  Microsoft  Windows ...

  9. 覆盖alert对话框-自制Jquery.alert插件

    Javascript 代码: (function ($) { 'use strict'; window.alert = $.alert = function (msg) { var defaultOp ...

  10. Codeforces Round #290 (Div. 2) _B找矩形环的三种写法

    http://codeforces.com/contest/510/status/B 题目大意 给一个n*m  找有没有相同字母连起来的矩形串 第一种并查集 瞎搞一下 第一次的时候把val开成字符串了 ...