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系列(13) This? Yes,this!
Jan 18 Javascript
JS.GetAllChild(element,deep,condition)使用介绍
Sep 21 Javascript
JavaScript中的比较操作符&gt;、=、
Dec 31 Javascript
使用Node.js配合Nginx实现高负载网络
Jun 28 Javascript
详解Matlab中 sort 函数用法
Mar 20 Javascript
全面了解函数声明与函数表达式、变量提升
Aug 09 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
JS获取url参数,JS发送json格式的POST请求方法
Mar 29 Javascript
webpack打包react项目的实现方法
Jun 21 Javascript
详解vue几种主动刷新的方法总结
Feb 19 Javascript
Node.js在图片模板上生成二维码图片并附带底部文字说明实现详解
Aug 07 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
Mar 07 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
vBulletin Forum 2.3.xx SQL Injection
2006/10/09 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
Laravel使用模型实现like模糊查询的例子
2019/10/24 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
javascript显示隐藏层比较不错的方法分析
2008/09/30 Javascript
extjs之去除s.gif的影响
2010/12/25 Javascript
Jquery图片延迟加载插件jquery.lazyload.js的使用方法
2014/05/21 Javascript
实例分析js和C#中使用正则表达式匹配a标签
2014/11/26 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
2016/05/30 Javascript
nodejs 的 session 简单使用
2016/06/06 NodeJs
javascript实现一个网页加载进度loading
2017/01/04 Javascript
swiper插件自定义切换箭头按钮
2017/12/28 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
详解Element 指令clickoutside源码分析
2019/02/15 Javascript
利用d3.js实现蜂巢图表带动画效果
2019/09/03 Javascript
全面解析JavaScript Module模式
2020/07/24 Javascript
vue 限制input只能输入正数的操作
2020/08/05 Javascript
多种类型jQuery网页验证码插件代码实例
2021/01/09 jQuery
python中的一些类型转换函数小结
2013/02/10 Python
Python的几个高级语法概念浅析(lambda表达式闭包装饰器)
2016/05/28 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
2016/06/14 Python
基于python3监控服务器状态进行邮件报警
2019/10/19 Python
Python-opencv 双线性插值实例
2020/01/17 Python
python+adb命令实现自动刷视频脚本案例
2020/04/23 Python
Paul’s Boutique官网:英国时尚手袋品牌
2018/03/31 全球购物
Sport-Thieme荷兰:购买体育用品
2019/08/25 全球购物
介绍一下MYSQL常用的优化技巧
2012/10/25 面试题
建筑安全生产责任书
2014/07/22 职场文书
物流专业专科生职业生涯规划书
2014/09/14 职场文书
司法局群众路线教育实践活动开展情况总结
2014/10/25 职场文书
2014年小学少先队工作总结
2014/12/18 职场文书
教师节祝酒词
2015/08/11 职场文书
给校长的建议书作文500字
2015/09/14 职场文书
品牌形象定位,全面分析
2019/07/23 职场文书
pandas:get_dummies()与pd.factorize()的用法及区别说明
2021/05/21 Python
V Rising 服务器搭建图文教程
2022/06/16 Servers