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 相关文章推荐
JavaScript Event学习第十章 一些可替换的事件对
Feb 10 Javascript
各浏览器对click方法的支持差异小结
Jul 31 Javascript
Node.js中使用Buffer编码、解码二进制数据详解
Aug 16 Javascript
判断window.onload是否多次使用的方法
Sep 21 Javascript
js实现数字每三位加逗号的方法
Feb 05 Javascript
jQuery实现鼠标经过弹出提示信息的地图热点效果
Aug 07 Javascript
跟我学习javascript的var预解析与函数声明提升
Nov 16 Javascript
BootStrap的JS插件之轮播效果案例详解
May 16 Javascript
jquery实现回车键触发事件(实例讲解)
Nov 21 jQuery
JS算法题之查找数字在数组中的索引位置
May 15 Javascript
vue柱状进度条图像的完美实现方案
Aug 26 Javascript
解决vue+webpack项目接口跨域出现的问题
Aug 10 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
桌面中心(一)创建数据库
2006/10/09 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
来自chinaz的ajax获取评论代码
2008/05/03 Javascript
js cookies实现简单统计访问次数
2009/11/24 Javascript
老鱼 浅谈javascript面向对象编程
2010/03/04 Javascript
JavaScript 继承使用分析
2011/05/12 Javascript
原生js实现给指定元素的后面追加内容
2013/04/10 Javascript
js中的eventType事件及其浏览器支持性介绍
2013/11/29 Javascript
js实现div的切换特效上一个下一个
2014/02/11 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
jquery插件hiAlert实现网页对话框美化
2015/05/03 Javascript
jquery实现美观的导航菜单鼠标提示特效代码
2015/09/06 Javascript
跟我学习javascript的基本类型和引用类型
2015/11/16 Javascript
JavaScript实现经纬度转换成地址功能
2017/03/28 Javascript
react以create-react-app为基础创建项目
2018/03/14 Javascript
vue车牌号校验和银行校验实战
2019/01/23 Javascript
python正则表达式抓取成语网站
2013/11/20 Python
Python验证码识别的方法
2015/07/10 Python
JS设计模式之责任链模式实例详解
2018/02/03 Python
Django--权限Permissions的例子
2019/08/28 Python
详解在Python中以绝对路径或者相对路径导入文件的方法
2019/08/30 Python
简单的Python调度器Schedule详解
2019/08/30 Python
Python run()函数和start()函数的比较和差别介绍
2020/05/03 Python
我的求职计划书
2014/01/10 职场文书
抗震救灾标语
2014/06/26 职场文书
先进事迹演讲稿
2014/09/01 职场文书
党员民主生活会个人整改措施材料
2014/09/16 职场文书
2014医学院领导班子对照检查材料思想汇报
2014/09/19 职场文书
给老师的一封感谢信
2015/01/20 职场文书
六一儿童节开幕词
2015/01/29 职场文书
单身证明范本
2015/06/15 职场文书
小学四年级作文之人物作文
2019/11/06 职场文书
Python3 使用pip安装git并获取Yahoo金融数据的操作
2021/04/08 Python
python之django路由和视图案例教程
2021/07/26 Python
Redis基本数据类型String常用操作命令
2022/06/01 Redis