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方法即可在想刷新页面时就刷新.如本例,这个方法 ...
随机推荐
- Java-包
定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中即可 ...
- Linux C 文件与目录4 将缓冲区数据写入磁盘
将缓冲区数据写入磁盘 所谓缓冲区,是Linux系统对文件的一种处理方式.在对文件进行写操作时,并没有立即把数据写入到磁盘,而是把数据写入到缓冲区.如果需要把数据立即写入到磁盘,可以使用sync函数.用 ...
- 推荐一款系统软件:Unity tweak tool
功能很多慢慢体会 在软件中心搜索unity tweak tool安装
- JavaScript插入节点
1. document.write("<p>This is inserted.</p>"); 该方法必须加在HTML文档内,违背了结构行为分离原则,不推荐. ...
- 11.9Daily Scrum
人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.823 数据库测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.824 实现视频浏览的功能 王 ...
- MVC 数据验证收集代码
控制器 Home using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- 【Subsets II】cpp
题目: Given a collection of integers that might contain duplicates, nums, return all possible subsets. ...
- C++ 排序函数 sort(),qsort()的含义与用法 ,字符串string 的逆序排序等
上学时我们很多学了很多种排序算法,不过在c++stl中也封装了sort等函数,头文件是#include <algorithm> 函数名 功能描述 sort 对给定区间所有元素进行排序 st ...
- github/gitlab 管理多个ssh key
github/gitlab 管理多个ssh key 以前只使用一个 ssh key 在github上提交代码,由于工作原因,需要再添加一个ssh key在公司的 gitlab上提交代码,下面记录下配置 ...
- 《编写高质量代码:改善Java程序的151个建议》笔记
To fight the unthinkable,you have to be willing to do the unthinkable. 不要在循环中使用try catch,应该放在循环的外面 ...