angularJS之$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 (===).
angularJS之$watch、$digest和$apply方法的更多相关文章
- 深入了解angularjs中的$digest与$apply方法,从区别聊到使用优化
壹 ❀ 引 如果有人问,在angularjs中修改模型数据为何视图会同步更新呢,我想大多数人一定会回答脏检查(Dirty Checking)相关概念.没错,在angularjs中作用域(scope) ...
- angularjs 中的$digest和$apply区别
$digest和$apply 在Angular中,有$apply和$digest两个函数,我们刚才是通过$digest来让这个数据应用到界面上.但这个时候,也可以不用$digest,而是使用$appl ...
- AngularJS中的digest循环$apply
欢迎大家指导与讨论 : ) 前言 Angular会拓展这个标准的浏览器流程,创建一个Angular上下文.这个Angular上下文指的是运行在Angular事件循环内的特定代码,该Angular事件循 ...
- angularjs $scope.$apply 方法详解
myApp.controller('firstController',function($scope,$interval){ $scope.date = new Date(); setInterval ...
- angularJS--apply() 、digest()和watch()方法
外文网址:http://www.sitepoint.com/understanding-angulars-apply-digest/ $apply()和$digest()在AngularJS中是两个核 ...
- angularJS之$apply()方法
这几天,根据buddy指定的任务,要分享一点angular JS的东西.对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的阻力还真是不少.不 ...
- angularJS中$apply()方法详解
这篇文章主要介绍了angularJS中$apply()方法详解,需要的朋友可以参考下 对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的 ...
- 【学】AngularJS日记(3)- $apply(), run()方法
$scope.$apply()方法可以强制$apply()里运行的函数所改变的model里的数据直接反应到view里,因为在angular的环境中,有时会用到原生js或者jquery的时候,这些行为有 ...
- angularJS $scope的$apply方法实现model刷新
控制器内,$scope有个$apply方法,可以代码更改model并同步更新页面.通常,控制器内的方法执行完毕后仅会自动刷新一次页面展示,使用$apply方法即可在想刷新页面时就刷新.如本例,这个方法 ...
随机推荐
- win8.1上安装vc6
win8.1上安装vc6 1.以管理员方式运行SETUP.EXE,然后一路下一步 2.这里需要一点点耐心,等10分钟左右就能过去,电脑会比较卡,有点像假死,还是没有死掉,等等就好了 3.这里选择vc6 ...
- Qt5 程序发布打包
关于qt5在win7下发布 & 打包 ----------------------------------------------------------------------------- ...
- JAVA类与对象(八)-----重写
重写:子类对父类的允许访问的方法的实现过程进行重新编写!返回值和形参都不能改变.即:外壳不变,核心重写! 好处:可以根据子类的需要,定义特定于自己的行为.也就是说子类能够根据需要实现父类的方法. cl ...
- win32 sdk显示一个载入的位图的方法
注:整理自网络文档 (1)加载位图 HANDLE LoadImage(HINSTANCE 来源实体,LPCTSTR 名称,UINT 位图类型, int 加载宽度,int 加载高度,UINT 加载方式) ...
- Shade勒索病毒 中敲诈病毒解密 如 issbakev9_Data.MDF.id-A1E.f_tactics@aol.com.xtbl 解决方法
[客户名称]:福建福州市某烘焙连锁企业 [软件名称]:思迅烘焙之星V9总部 [数据库版本]:MS SQL server 2000 [数据库大小]:4.94GB [问题描述]:由于客户服务器安全层薄弱 ...
- M1事后分析报告(Postmortem Report)
M1事后分析报告(Postmortem Report) 设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们项目组所开发的软件为一个基于Andro ...
- 揭开NodeJS的神秘面纱!
一.NodeJS是什么? Node是一个服务器端JavaScript解释器.Node.js是一套用来编写高性能网络服务器的JavaScript包. 二.Node的目标是什么? Node 公开宣称的目标 ...
- 前端之JavaScript第一天学习(1)-JavaScript 简介
javaScript 是世界上最流行的编程语言. 这门语言可用于 HTML 和 web,更可广泛用于服务器.PC.笔记本电脑.平板电脑和智能手机等设备. JavaScript 是脚本语言 JavaSc ...
- Byte measurements
- window.showModalDialog的传值和返回值
window.showModalDialog(URL,dialogArgments,features) 打开一个新窗口 URL为要将打开的网页地址. dialogArgments为设定好传递给新视窗网 ...