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 相关文章推荐
日期函数扩展类Ver0.1.1
Sep 07 Javascript
在js中单选框和复选框获取值的方式
Nov 06 Javascript
基于Jquery的简单图片切换效果
Jan 06 Javascript
jquery.cookie.js 操作cookie实现记住密码功能的实现代码
Apr 27 Javascript
js中创建对象的几种方式示例介绍
Jan 26 Javascript
javascript动态设置样式style实例分析
May 13 Javascript
jQuery实现点击后标记当前菜单位置(背景高亮菜单)效果
Aug 22 Javascript
Extjs表单输入框异步校验的插件实现方法
Mar 20 Javascript
详解Vue 方法与事件处理器
Jun 20 Javascript
JavaScript之map reduce_动力节点Java学院整理
Jun 29 Javascript
基于Vue的SPA动态修改页面title的方法(推荐)
Jan 02 Javascript
浅入深出Vue之组件使用
Jul 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的博客ping服务代码
2012/02/04 PHP
php检测图片木马多进制编程实践
2013/04/11 PHP
Linux Apache PHP Oracle 安装配置(具体操作步骤)
2013/06/17 PHP
网站防止被刷票的一些思路与方法
2015/01/08 PHP
php用户登录之cookie信息安全分析
2016/05/13 PHP
利用PHP判断是否是连乘数字串的方法示例
2017/07/03 PHP
JavaScript面象对象设计
2008/04/28 Javascript
鼠标选择动态改变网页背景颜色的JS代码
2013/12/10 Javascript
javascript判断office版本示例
2014/04/11 Javascript
Javascript验证Visa和MasterCard信用卡号的方法
2015/07/27 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
AngularJS路由Ui-router模块用法示例
2017/05/29 Javascript
webpack+vuex+axios 跨域请求数据的示例代码
2018/03/06 Javascript
JS滚轮控制图片缩放大小和拖动的实例代码
2018/11/20 Javascript
js实现金山打字通小游戏
2020/07/24 Javascript
Ant Design的可编辑Tree的实现操作
2020/10/31 Javascript
[01:04:30]Fnatic vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
使用PyCharm配合部署Python的Django框架的配置纪实
2015/11/19 Python
python中PIL安装简单教程
2016/04/21 Python
wxpython中自定义事件的实现与使用方法分析
2016/07/21 Python
Python3爬虫全国地址信息
2019/01/05 Python
python 穷举指定长度的密码例子
2020/04/02 Python
python与idea的集成的实现
2020/11/20 Python
如何设置PyCharm中的Python代码模版(推荐)
2020/11/20 Python
Html5 audio标签样式的修改
2016/01/28 HTML / CSS
Intimissimi德国网上商店:意大利知名内衣品牌
2018/04/03 全球购物
党员自我批评与反省材料
2014/02/10 职场文书
感恩节红领巾广播稿
2014/02/11 职场文书
铁路安全事故反思
2014/04/26 职场文书
质量安全标语
2014/06/07 职场文书
教师群众路线心得体会
2014/11/04 职场文书
2014小学数学教师个人工作总结
2014/12/18 职场文书
社会心理学学习心得体会
2016/01/22 职场文书
Python中相见恨晚的技巧
2021/04/13 Python
详解CSS伪元素的妙用单标签之美
2021/05/25 HTML / CSS