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()是如何工作的 ...
随机推荐
- Keepalived 主备配置
keepalived主备或多主多备,配置都是一样配置方法,只是搭建多少的问题. 1.keepalived安装 参考:https://www.cnblogs.com/zwcry/p/9542867.ht ...
- [原创]spring及springmvc精简版--AOP
接上一篇:[原创]spring及springmvc精简版--IOC 理解AOP.java是一种面向对象的语言.而AOP是面向切面,在我看来是面向逻辑或者业务编程,它是对一组逻辑的抽象和分配. 经典例子 ...
- Apache的order、allow、deny
Allow和Deny可以用于apache的conf文件或者.htaccess文件中(配合Directory, Location, Files等),用来控制目录和文件的访问授权. 所以,最常用的是:Or ...
- linux+udp+server+client
一.客户端 #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include ...
- gcc编译c、c++入门
一.c语言 1.在当前目录下新建c文件 $:vim hello.c 2.按i进入编辑模式.按esc退出编辑模式,输入源代码 #include <stdio.h> int main(void ...
- tcp底层连接过程(c语言)
在用了多种上位机开发环境,包括mfc.Qt.C#之后,发现它们的API都是对底层协议的(可以说是C语言)的封装,所以了解了底层协议,任意换上位机开发环境都是没问题的. 1.服务器创建套接字socket ...
- Mysql 导出导入
MySQL数据库导出 以root登录vps,执行以下命令导出. 1./usr/local/mysql/bin/mysqldump -u root -p123456 zhumaohai > /ho ...
- linux 上传scp 压缩tar命令
1.Linux 上传scp 1)上传文件与文件夹 scp file weblogic@xx.xxx.xxx.xxx:~/songjd/ scp -r filefolder weblogic@xxx.x ...
- 報錯:One or more validation errors were detected during model generation:System.Data.Edm.EdmEntityType: : EntityType 'Movie' has no key
報錯:One or more validation errors were detected during model generation:System.Data.Edm.EdmEntityType ...
- java:RandomAccessFile随机读取文件内容
RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须是可知的.但是该类仅限于操作文件. ...