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 相关文章推荐
DOM相关内容速查手册
Feb 07 Javascript
利用js对象弹出一个层
Mar 26 Javascript
js实现字符串的16进制编码不加密
Apr 25 Javascript
JavaScript实现更改网页背景与字体颜色的方法
Feb 02 Javascript
深入探寻seajs的模块化与加载方式
Apr 14 Javascript
干货分享:让你分分钟学会javascript闭包
Dec 25 Javascript
jquery实现页面常用的返回顶部效果
Mar 04 Javascript
bootstrap IE8 兼容性处理
Mar 22 Javascript
jQuery插件FusionCharts绘制2D柱状图和折线图的组合图效果示例【附demo源码】
Apr 10 jQuery
JavaScript日期工具类DateUtils定义与用法示例
Sep 03 Javascript
JavaScript使用Math.random()生成简单的验证码
Jan 21 Javascript
js实现页面图片消除效果
Mar 24 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/10/09 PHP
模仿OSO的论坛(二)
2006/10/09 PHP
创建配置文件 用PHP写出自己的BLOG系统 2
2010/04/12 PHP
php 在windows下配置虚拟目录的方法介绍
2013/06/26 PHP
一个漂亮的php验证码类(分享)
2013/08/06 PHP
php 利用socket发送HTTP请求(GET,POST)
2015/08/24 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
laravel实现批量更新多条记录的方法示例
2017/10/22 PHP
用javascript实现无刷新更新数据的详细步骤 asp
2006/12/26 Javascript
jQuery修改CSS伪元素属性的方法
2014/07/30 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
基于BootStrap Metronic开发框架经验小结【五】Bootstrap File Input文件上传插件的用法详解
2016/05/12 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
2018/07/10 Javascript
原生JS实现萤火虫效果
2020/03/07 Javascript
JavaScript中ES6规范中let和const的用法和区别
2020/08/06 Javascript
[01:13:17]Secret vs NB 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:14]DOTA2 7.22版本新增神杖效果展示(智力英雄篇)
2019/05/29 DOTA
使用python语言,比较两个字符串是否相同的实例
2018/06/29 Python
聊聊python里如何用Borg pattern实现的单例模式
2019/06/06 Python
解决安装python3.7.4报错Can''t connect to HTTPS URL because the SSL module is not available
2019/07/31 Python
纯CSS3实现的阴影效果
2014/12/24 HTML / CSS
宝拉珍选澳大利亚官方购物网站:Paula’s Choice澳大利亚
2016/09/13 全球购物
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
网络工程师面试(三木通信技术有限公司)
2013/06/05 面试题
写给老师的表扬信
2014/01/21 职场文书
中文专业学生自我评价范文
2014/02/06 职场文书
致1500米运动员广播稿
2014/02/07 职场文书
安全责任书范文
2014/03/12 职场文书
医生见习报告范文
2014/11/03 职场文书
2016教师给学生的毕业寄语
2015/12/04 职场文书
如何计划开一家便利店?
2019/07/31 职场文书
使用springboot暴露oracle数据接口的问题
2021/05/07 Oracle
Django使用echarts进行可视化展示的实践
2021/06/10 Python
python 中yaml文件用法大全
2021/07/04 Python
Python制作动态字符画的源码
2021/08/04 Python
Apache SkyWalking 监控 MySQL Server 实战解析
2022/09/23 Servers