angular的$watch,$digest和$apply
第一部分:$watch
$watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你。
$watch(watchExpression, listener, objectEquality);
每个参数的说明如下:
watchExpression:监听的对象,它可以是一个angular表达式如'name',或函数如function(){return $scope.name}。
listener:当watchExpression变化时会被调用的函数或者表达式,它接收3个参数:newValue(新值), oldValue(旧值), scope(作用域的引用)
objectEquality:是否深度监听,如果设置为true,它告诉Angular检查所监控的对象中每一个属性的变化. 如果你希望监控数组的个别元素或者对象的属性而不是一个普通的值, 那么你应该使用它
可参考:
http://yuankeqiang.lofter.com/post/8de51_1454f93
http://www.angularjs.cn/A0a6
官网:http://docs.angularjs.cn/api/ng/type/$rootScope.Scope
第二部分:$watch,$digest和$apply
最近项目上使用了比较多的angular JS,一直都对它感觉比较陌生,总觉得有点反直觉,这段时间,准备下定决心弄明白,这个框架到底是怎么一回事,以及它的工作原理,生命周期……一点一点的啃完它吧。首先,让我们先来看看watch、digest、$apply这三个方法吧!
- $watch(watchExpression, listener, objectEquality)
| Param | Type | Details |
| watchExpression |
function() string |
Expression that is evaluated on each $digest cycle. A change in the return value triggers a call to the listener.
|
| listener (optional) |
function() string |
Callback called whenever the return value of the watchExpressionchanges.
|
| objectEquality (optional) |
boolean | Compare object for equality rather than for reference. |
从表格中可以看到,watchExpression和listener可以是一个string,也可以是一个function(scope)。该表达式在每次调用了$digest方法之后都会重新算值,如果返回值发生了改变,listener就会执行。在判断newValue和oldValue是否相等时,会递归的调用angular.equals方法。在保存值以备后用的时候调用的是angular.copy方法。listener在执行的时候,可能会修改数据从而触发其他的listener或者自己直到没有检测到改变为止。Rerun Iteration的上限是10次,这样能够保证不会出现死循环的情况。
$watch的基本结构如下:

//$scope.$watch(<function/expression>, <handler>);
$scope.$watch('foo', function(newVal, oldVal) {
console.log(newVal, oldVal);
});
//or
$scope.$watch(function() {
return $scope.foo;
}, function(newVal, oldVal) {
console.log(newVal, oldVal);
});

- $digest()
该方法会触发当前scope以及child scope中的所有watchers,因为watcher的listener可能会改变model,所以$digest方法会一直触发watchers直到不再有listener被触发。当然这也有可能会导致死循环,不过angular也帮我们设置了上限10!否则会抛出“Maximum iteration limit exceeded.”。
通常,我们不在controller或者directive中直接调用digest方法,而是调apply方法,让apply方法去调用digest方法。
如何调用该方法呢?
$scope.$digest();
- $apply(exp)
| Param | Type | Details |
| exp (optional) |
string function() |
An angular expression to be executed.
|
个人理解,apply方法就是将digest方法包装了一层,exp是可选参数,可以是一个string,也可以是function(scope)。伪代码(来自官方文档)如下:

function $apply(expr) {
try {
return$eval(expr);
} catch(e) {
$exceptionHandler(e);
} finally {
$root.$digest();
}
}

$apply方法使得我们可以在angular里面执行angular框架之外的表达式,比如说:浏览器DOM事件、setTimeout、XHR或其他第三方的库。由于我们要在angular框架内调用,我们必须得准备相应的scope。调用方式如下:

$scope.$apply('foo = "test"');
//or
$scope.$apply(function(scope) {
scope.foo = 'test';
});
//or
$scope.$apply(function(){
$scope.foo = 'test';
});

- watch、digest、$apply是如何与视图的更新相关联的呢?
- directive给scope上的一个model注册watch来监视它的变化,listener会去更新DOM元素的值。
- directive给DOM中的一些元素注册event handler,它们会取得DOM中元素的值,然后更新到scope上的model中去。它也会触发apply或者$digest。
- 当你通过框架更新了scope上model的值,比如说:http.get(),当它完成后也会触发$digest方法。
- digest会去检查directive注册的watch,发现值被修改就会触发相关联的handler,然后更新DOM元素。
至于angular js为什么要这么做,请看我上一篇博客angular js之scope.$apply方法。
- $watch
- 当scope上的值发生变化时,尽量在directive中使用watch去更新DOM。
- 尽量不要再controller中使用$watch方法,它会增加测试的复杂度,而且也不必要。可以使用scope上的方法去更新被改变的值。
- digest、apply
- 在directive中使用digest/apply使angular知道一个异步请求完成后的变化,比如说DOM Event。
- 在service中使用digest/apply使angular知道一个异步操作已经完成,比如说WebSocket、或者第三方的库。
- 尽量不要再controller中使用digest/apply,这样的话测试起来会比较困难。
===============================================================================
- 关于angular.equals方法
该方法支持value types,regular expressions、arrays、objects。官方文档写的很清楚:
Two objects or values are considered equivalent if at least one of the following is true:
- Both objects or values pass === comparison.
- Both objects or values are of the same type and all of their properties are equal by comparing them with angular.equals.
- Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- Both values represent the same regular expression (In JavasScript, /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual representation matches).
During a property comparison, properties of function type and properties with names that begin with $ are ignored.
Scope and DOM Window objects are being compared only by identify (===).
来源:http://www.cnblogs.com/penghongwei/p/3400535.html
angular的$watch,$digest和$apply的更多相关文章
- Angular 学习笔记 :初识 $digest , $watch , $apply,浅析用法 。
传统的浏览器事件循环 :浏览器本身一直在等待事件,并作出响应.如果你点击一个button或者在input 中输入字符,我们在 JS 中 监听这些事件并设定了回调函数,那么这些事件被触发以后,回调函数就 ...
- $watch、$digest、$apply
$watch.$digest.$apply $watch 代表的就是对数据源的监听,当数据源发生变化,就会触发第二个参数的回调函数 $digest 代表触发一个数据源变化的事件 $apply 代表对于 ...
- angularJS之$watch、$digest和$apply方法
最近项目上使用了比较多的angular JS,一直都对它感觉比较陌生,总觉得有点反直觉,这段时间,准备下定决心弄明白,这个框架到底是怎么一回事,以及它的工作原理,生命周期……一点一点的啃完它吧.首先, ...
- angularjs 中的$digest和$apply区别
$digest和$apply 在Angular中,有$apply和$digest两个函数,我们刚才是通过$digest来让这个数据应用到界面上.但这个时候,也可以不用$digest,而是使用$appl ...
- 深入了解angularjs中的$digest与$apply方法,从区别聊到使用优化
壹 ❀ 引 如果有人问,在angularjs中修改模型数据为何视图会同步更新呢,我想大多数人一定会回答脏检查(Dirty Checking)相关概念.没错,在angularjs中作用域(scope) ...
- angular核心$watch,$digest,$apply之间的联系
浏览器事件发生时,会在浏览器的上下文window中执行,而angular有自己的上下文angular content,angular 事件在自己的上下文angular content中执行. $wat ...
- angular之 $watch 和$digest 和$apply和$observe的区别
$watch 代表的就是对数据源的监听,当数据源发生变化,就会触发第二个参数的回调函数 $digest 代表触发一个数据源变化的事件 $apply 代表对于$digest的一个封装,他多了一个参数 . ...
- AngularJS中的digest循环$apply
欢迎大家指导与讨论 : ) 前言 Angular会拓展这个标准的浏览器流程,创建一个Angular上下文.这个Angular上下文指的是运行在Angular事件循环内的特定代码,该Angular事件循 ...
- 理解Angular中的$apply()以及$digest()
$apply()和$digest()在AngularJS中是两个核心概念,但是有时候它们又让人困惑.而为了了解AngularJS的工作方式,首先需要了解$apply()和$digest()是如何工作的 ...
随机推荐
- Android下Opengl ES实现单屏幕双眼显示
http://blog.csdn.net/u011371324/article/details/68946779 默认情况下,Opengl ES使用系统提供的帧缓冲区作为绘图表面,一般情况下,如果只在 ...
- pppoe白皮书
转:https://blog.csdn.net/achejq/article/details/19478811 PPPoE技术白皮书 关键词:PPP,Ethernet,PPPoE 摘 要:PPP ...
- 手把手教你使用eclipse+qemu+gdb来单步调试ARM内核【学习笔记】
平台信息:linux4.0 平台:qemu 作者:庄泽彬 说明:笨叔叔的Linux视频的笔记 一.编译linux源码 export CROSS_COMPILE=arm-linux-gnueabi- e ...
- vRA7 Business error “Untrusted certificate chain”
报错截图: 服务无法注册 第一步:登录vRB 5480页面,取消到vRA的注册 第二部:SSH登录到VRB中,查看bio-ssl.keystore.password. cat /shared/cata ...
- linux设置系统时间与时区以及设置bios时间同步系统时间
有装过Linux系统的人,可能都会有这样的经历,就是该机器安装windows系统时,时间正确,但是安装了linux系统后,尽管时区选择正确,也会发现系统时间不对.这是由于安装系统时采用了UTC,那么什 ...
- Excel下载打不开
1.问题描述:今天遇到个问题,对于定时发送邮件,前两天还正常,今天发现邮件能收到,但打不开,显示如下错误: 预览邮件显示: 点击Excel打开,显示如下: 2.问题解决方案 删除对于服务器上部分空间内 ...
- 重置密码解决MySQL for Linux错误 ERROR 1045 (28000)
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
- mvn库
http://maven.aliyun.com/nexus/content/groups/public/ http://mvnrepository.com/http://search.maven.or ...
- IOS 被拒 关于 iPhone running iOS 10.3.1 on Wi-Fi connected to an IPv6 network.
问题: Guideline 2.1 - Performance Thank you for your resubmission. However, we discovered one or more ...
- Codeforces Round #386 (Div. 2) C D E G
一场比较简单的题 比较脑洞 C 如果坐车比较快的话 先走不如等车 所以最后的ans是min(纯走路,纯坐车) 讨论一下坐车时间 D 因为k一定是>=1的 所以当a=b的时候 GBGBGB这样间隔 ...