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 相关文章推荐
用于判断用户注册时,密码强度的JS代码
Jan 01 Javascript
javascript返回顶部效果(自写代码)
Jan 06 Javascript
js window.print实现打印特定控件或内容
Sep 16 Javascript
js设置组合快捷键/tabindex功能的方法
Nov 21 Javascript
JavaScript实现下拉列表框数据增加、删除、上下排序的方法
Aug 11 Javascript
Jquery代码实现图片轮播效果(一)
Aug 12 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
Sep 27 Javascript
bootstrap table操作技巧分享
Feb 15 Javascript
对于Javascript 执行上下文的全面了解
Sep 05 Javascript
Vue.set()实现数据动态响应的方法
Feb 07 Javascript
webpack4+express+mongodb+vue实现增删改查的示例
Nov 08 Javascript
微信小程序车牌号码模拟键盘输入功能的实现代码
Nov 11 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 fopen 读取带中文URL地址的一点见解
2012/09/25 PHP
用php随机生成福彩双色球号码的2种方法
2013/02/04 PHP
浅析PHP页面局部刷新功能的实现小结
2013/06/21 PHP
php查询mysql数据库并将结果保存到数组的方法
2015/03/18 PHP
微信自定义菜单的处理开发示例
2015/04/16 PHP
php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
2018/09/28 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
php gethostbyname获取域名ip地址函数详解
2010/01/24 Javascript
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
2012/08/09 Javascript
html文件中jquery与velocity变量中的$冲突的解决方法
2013/11/01 Javascript
Jquery解析Json格式数据过程代码
2014/10/17 Javascript
javascript父子页面通讯实例详解
2015/07/17 Javascript
jQuery移动web开发之页面跳转和加载外部页面的实现
2015/12/04 Javascript
jQuery判断网页是否已经滚动到浏览器底部的实现方法
2017/10/27 jQuery
Vue.js通用应用框架-Nuxt.js的上手教程
2017/12/25 Javascript
详解vue-meta如何让你更优雅的管理头部标签
2018/01/18 Javascript
JavaScript实现简单随机点名器
2019/11/21 Javascript
es6 super关键字的理解与应用实例分析
2020/02/15 Javascript
JavaScript 空间坐标的使用
2020/08/19 Javascript
js绘制一条直线并旋转45度
2020/08/21 Javascript
介绍Python中几个常用的类方法
2015/04/08 Python
Python找出list中最常出现元素的方法
2016/06/14 Python
Python selenium 三种等待方式详解(必会)
2016/09/15 Python
如何利用Fabric自动化你的任务
2016/10/20 Python
python使用response.read()接收json数据的实例
2018/12/19 Python
英国第一家领先的在线处方眼镜零售商:Glasses Direct
2018/02/23 全球购物
华三通信H3C面试题
2015/05/15 面试题
房产公证书范本
2014/04/10 职场文书
小学生综合素质评语
2014/04/23 职场文书
材料化学专业求职信
2014/07/15 职场文书
亲子阅读的活动方案
2014/08/15 职场文书
2015年世界环境日活动总结
2015/02/11 职场文书
2015年七一建党节演讲稿
2015/03/19 职场文书
2015年重阳节主持词
2015/07/04 职场文书
大学生安全教育主题班会
2015/08/12 职场文书
新手入门Jvm-- JVM对象创建与内存分配机制
2021/06/18 Java/Android