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 双色表格实现代码
Dec 08 Javascript
node.js中的fs.closeSync方法使用说明
Dec 17 Javascript
jquery实现鼠标拖拽滑动效果来选择数字的方法
May 04 Javascript
html5+javascript实现简单上传的注意细节
Apr 18 Javascript
require.js配合插件text.js实现最简单的单页应用程序
Jul 12 Javascript
Bootstrap Table使用方法解析
Oct 19 Javascript
Javascript设计模式之装饰者模式详解篇
Jan 17 Javascript
node koa2实现上传图片并且同步上传到七牛云存储
Jul 31 Javascript
分享vue里swiper的一些坑
Aug 30 Javascript
在vue项目中使用sass语法问题
Jul 18 Javascript
javascript网页随机点名实现过程解析
Oct 15 Javascript
Javascript ParentNode和ChildNode接口原理解析
Mar 16 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使用unset()删除数组中某个单元(键)的方法
2015/02/17 PHP
新浪刚打开页面出来的全屏广告代码
2007/04/02 Javascript
javascript 模式设计之工厂模式详细说明
2010/05/10 Javascript
用js替换除数字与逗号以外的所有字符的代码
2014/06/07 Javascript
每天一篇javascript学习小结(RegExp对象)
2015/11/17 Javascript
canvas实现手机端用来上传用户头像的代码
2016/10/20 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
微信小程序 开发之顶部导航栏实例代码
2017/02/23 Javascript
JQuery 选择器、DOM节点操作练习实例
2017/09/28 jQuery
从vue源码解析Vue.set()和this.$set()
2018/08/30 Javascript
vuex存取值和映射函数使用说明
2020/07/24 Javascript
[05:08]第一届“网鱼杯”DOTA2比赛精彩集锦
2014/09/05 DOTA
[01:00:35]2018DOTA2亚洲邀请赛3月30日B组 EffcetVSMineski
2018/03/31 DOTA
[01:10:58]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
[46:28]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.23
2019/09/05 DOTA
[39:19]完美世界DOTA2联赛PWL S2 SZ vs LBZS 第二场 11.26
2020/11/30 DOTA
Python批量按比例缩小图片脚本分享
2015/05/21 Python
Python numpy实现数组合并实例(vstack,hstack)
2018/01/09 Python
django如何自己创建一个中间件
2019/07/24 Python
Python3 pandas 操作列表实例详解
2019/09/23 Python
Windows10下Tensorflow2.0 安装及环境配置教程(图文)
2019/11/21 Python
python计算导数并绘图的实例
2020/02/29 Python
Python使用内置函数setattr设置对象的属性值
2020/10/16 Python
如何通过Python实现RabbitMQ延迟队列
2020/11/28 Python
突破canvas语法限制 让他支持链式语法
2012/12/24 HTML / CSS
欧洲最大的美妆零售网站:Feelunique
2017/01/14 全球购物
DOM和JQuery对象有什么区别
2016/11/11 面试题
材料专业毕业生求职信
2014/02/26 职场文书
竞聘演讲稿精彩开头和结尾
2014/05/14 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
党支部审查意见
2015/06/02 职场文书
特种设备安全管理制度
2015/08/06 职场文书
2016年公司新年寄语
2015/08/17 职场文书
2015年度女工工作总结
2015/10/22 职场文书
导游词之重庆渣滓洞
2020/01/08 职场文书
实例详解Python的进程,线程和协程
2022/03/13 Python