AngularJS中的$watch(),$digest()和$apply()区分


Posted in Javascript onApril 04, 2016

AngularJS $scope里面的$watch(),$digest()和$apply()是AngularJS的核心函数,学习AngularJS必须理解这几个函数。

在绑定$scope中的变量到view的时候,AngularJS自动在内部创建一个"Watch"。"Watch"用于监听AngularJS scope中变量的改变。可以通过调用$scope.$watch()这个方法来创建"Watch"。

$scope.$digest()函数会循环访问所有的watches,并检测其所监听的$scope中的变量是否改变。如果变量发生改变,会调用该变量对应的监听函数。监听函数可以实现很多操作,比如让html里面的text文本显示最新的变量值。可见,$scope.$digest是可以触发数据绑定更新的。

大部分情况下,AngualrJS会自动调用$scope.$watch()和$scope.$digest()函数,但是在某些情况下,我们需要手动调用他们,因此,有必要了解他们是怎么工作的。

$scope.$apply()这个函数会先执行一些代码,之后在调用$scope.$digest()。所有的watches会被检测一次,相应的监听函数也会被执行。$scope.$apply()在AngularJS与其它javascript代码集成时是很有用的。

接下来我们具体的讲解下$watch(), $digest() 和 $apply()。

$watch()
$watch(watchExpression, listener, [objectEquality])

watchExpression:监听对象,可以是string或者function(scope){}

listener:监听对象发生改变时执行的回调函数function(newVal,oldVal,scope){}

objectEquality:是否深度监听,如果设置为true,它告诉Angular检查所监控的对象中每一个属性的变化。如果你希望监控数组的个别元素或者对象的属性而不是一个普通的值, 那么你应该使用它。(默认值:false)

$digest()
检测当前scope以及子scope中所有的watches,因为监听函数会在执行过程中修改model(scope中的变量),$digest()会一直被调用直到model没有再变。当调用超过10次时,$digest()会抛出一个异常"Maximum iteration limit exceeded',以此来防止程序进入一个死循环。

$apply()
$apply([exp])

exp:string或者function(scope){}

$apply()生命周期伪代码示意图如下

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

Example
下面我们通过一个例子来说明$watch,$digest和$apply。

<script>
var module = angular.module("myapp", []);
var myController1 = module.controller("myController", function($scope) {
  $scope.data = { time : new Date() };
  $scope.updateTime = function() {
    $scope.data.time = new Date();
  }
   
  document.getElementById("updateTimeButton")
      .addEventListener('click', function() {
    console.log("update time clicked");
    $scope.data.time = new Date();
  });
});
</script>
<body ng-app="myapp">
<div ng-controller="myController">
  {{data.time}}
 
  <br/>
  <button ng-click="updateTime()">update time - ng-click</button>
  <button id="updateTimeButton" >update time</button>
</div>
</body>

这段代码会绑定$scope.data.time到HTML中显示出来,同时这个绑定会自动创建一个watch来监听$scope.date.time的变化。此外,这里还有2个按钮,第一个按钮是通过ng-click Directive来调用$scope.updateTime方法,之后AngularJS会自动执行$scope.$digest()使最新的时间显示到HTML中。第二个按钮是通过javascript代码添加一个点击事件,以此来更新HTML中的时间。但是第二个按钮是不能工作的,它的解决办法是在点击事件的最后手动的去调用$scope.$digest()方法,如下:

document.getElementById("updateTimeButton")
    .addEventListener('click', function() {
  console.log("update time clicked");
  $scope.data.time = new Date();
  $scope.$digest();
});

另外一个解决办法是调用$scope.$apply(),如下:

document.getElementById("updateTimeButton")
    .addEventListener('click', function() {
  $scope.$apply(function(){
      console.log("update time clicked");
      $scope.data.time = new Date();
    }
  );
});

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
jquery offset函数应用实例
Nov 14 Javascript
谷歌地图打不开的解决办法
Aug 07 Javascript
jQuery+css3动画属性制作猎豹浏览器宽屏banner焦点图
Mar 16 Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
Sep 21 Javascript
angular实现表单验证及提交功能
Feb 01 Javascript
漂亮实用的页面loading(加载)封装代码
Feb 03 Javascript
JS中showModalDialog关闭子窗口刷新主窗口用法详解
Mar 25 Javascript
bootstrap table动态加载数据示例代码
Mar 25 Javascript
JavaScript实现三级联动效果
Jul 15 Javascript
ES5新增数组的实现方法
May 12 Javascript
vue实现简单图片上传
Jun 30 Javascript
TypeScript实用技巧 Nominal Typing名义类型详解
Sep 23 Javascript
Angular 根据 service 的状态更新 directive
Apr 03 #Javascript
jQuery中的Deferred和promise 的区别
Apr 03 #Javascript
再次谈论React.js实现原生js拖拽效果引起的一系列问题
Apr 03 #Javascript
jQuery qrcode生成二维码的方法
Apr 03 #Javascript
Node.js 应用跑得更快 10 个技巧
Apr 03 #Javascript
AngularJs 60分钟入门基础教程
Apr 03 #Javascript
深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
Apr 03 #Javascript
You might like
PHP生成静态页面详解
2006/12/05 PHP
需要注意的几个PHP漏洞小结
2012/02/05 PHP
PHP英文字母大小写转换函数小结
2014/05/03 PHP
PHP人民币金额转大写实例代码
2015/10/02 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
js中关于一个分号的崩溃示例
2013/11/11 Javascript
TinyMCE提交AjaxForm获取不到数据的解决方法
2015/03/05 Javascript
jquery简单实现外部链接用新窗口打开的方法
2015/05/30 Javascript
js实现数组冒泡排序、快速排序原理
2016/03/08 Javascript
javaScript事件机制兼容【详细整理】
2016/07/23 Javascript
浅谈JS继承_借用构造函数 &amp; 组合式继承
2016/08/16 Javascript
浅谈js控制li标签排序问题 js调用php函数的方法
2016/10/16 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
jQuery的三种bind/One/Live/On事件绑定使用方法
2017/02/23 Javascript
独立部署小程序基于nodejs的服务器过程详解
2019/06/24 NodeJs
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
微信小程序服务器日期格式化问题
2020/01/07 Javascript
解决vuex数据页面刷新后初始化操作
2020/07/26 Javascript
[36:13]Mineski vs iG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[01:10:49]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
Python内置函数之filter map reduce介绍
2014/11/30 Python
Python使用自带的ConfigParser模块读写ini配置文件
2016/06/26 Python
在PyCharm中三步完成PyPy解释器的配置的方法
2018/10/29 Python
Python实现自定义读写分离代码实例
2019/11/16 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
Html5游戏开发之乒乓Ping Pong游戏示例(二)
2013/01/21 HTML / CSS
南非最大的花卉和送礼服务:NetFlorist
2017/09/13 全球购物
酒店服务实习自我鉴定
2013/09/22 职场文书
致长跑运动员广播稿
2014/01/31 职场文书
五一手机促销方案
2014/03/08 职场文书
机关单位动员会主持词
2014/03/20 职场文书
田径运动会广播稿
2015/08/19 职场文书
银行文明优质服务培训心得体会
2016/01/09 职场文书
详解nodejs内置模块
2021/05/06 NodeJs
Python基本知识点总结
2022/04/07 Python
Nginx流量拷贝ngx_http_mirror_module模块使用方法详解
2022/04/07 Servers