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 相关文章推荐
ExtJS 简介 让你知道extjs是什么
Dec 29 Javascript
最简单的jQuery程序 入门者学习
Jul 09 Javascript
js获取dom的高度和宽度(可见区域及部分等等)
Jun 13 Javascript
解决Jquery load()加载GB2312页面时出现乱码的两种方案
Sep 10 Javascript
jquery实现图片上传之前预览的方法
Jul 11 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
Aug 19 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
Oct 28 jQuery
Vue.js+Layer表格数据绑定与实现更新的实例
Mar 07 Javascript
vue移动端微信授权登录插件封装的实例
Aug 28 Javascript
使用layui+ajax实现简单的菜单权限管理及排序的方法
Sep 10 Javascript
ES10的13个新特性示例(小结)
Sep 23 Javascript
JavaScript数组常用的增删改查与其他属性详解
Oct 13 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 array_flip() 删除数组重复元素
2009/01/14 PHP
php实现统计网站在线人数的方法
2015/05/12 PHP
Zend Framework框架中实现Ajax的方法示例
2017/06/27 PHP
javascript html 静态页面传参数
2009/04/10 Javascript
jquery获取URL中参数解决中文乱码问题的两种方法
2013/12/18 Javascript
javascript中验证大写字母、数字和中文
2014/01/15 Javascript
详细分析使用AngularJS编程中提交表单的方式
2015/06/19 Javascript
javascript实现checkbox复选框实例代码
2016/01/10 Javascript
动态创建按钮的JavaScript代码
2016/01/29 Javascript
Bootstrap入门书籍之(一)排版
2016/02/17 Javascript
浅谈jquery页面初始化的4种方式
2016/11/27 Javascript
jquery——九宫格大转盘抽奖实例
2017/01/16 Javascript
jQuery倒计时代码(超简单)
2017/02/27 Javascript
mpvue跳转页面及注意事项
2018/08/03 Javascript
JS实现动态添加外部js、css到head标签的方法
2019/06/05 Javascript
javascript实现前端input密码输入强度验证
2020/06/24 Javascript
JavaScript如何操作css
2020/10/24 Javascript
[53:15]Mineski vs iG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
[04:00]黄浦江畔,再会英雄——完美世界DOTA2 TI9应援视频
2019/07/31 DOTA
Python基于win32ui模块创建弹出式菜单示例
2018/05/09 Python
对Tensorflow中权值和feature map的可视化详解
2018/06/14 Python
Python对象属性自动更新操作示例
2018/06/15 Python
Django Rest framework之认证的实现代码
2018/12/17 Python
Python基础教程之异常详解
2019/01/10 Python
利用rest framework搭建Django API过程解析
2019/08/31 Python
tensorflow实现测试时读取任意指定的check point的网络参数
2020/01/21 Python
Python 必须了解的5种高级特征
2020/09/10 Python
Python-split()函数实例用法讲解
2020/12/18 Python
高中综合实践活动总结
2014/07/07 职场文书
党建工作汇报材料
2014/12/24 职场文书
公司文体活动总结
2015/05/07 职场文书
2015年审计人员工作总结
2015/05/26 职场文书
高中语文教材(文学文化常识大全一)
2019/08/13 职场文书
PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库
2021/04/16 PHP
Go 内联优化让程序员爱不释手
2022/06/21 Golang
MySQL常用慢查询分析工具详解
2022/08/14 MySQL