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 ajax 登录验证实现代码
Sep 23 Javascript
基于jquery的放大镜效果
May 30 Javascript
Javascript动态创建div的方法
Feb 09 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
Oct 21 Javascript
JS和jQuery通过this获取html标签中的属性值(实例代码)
Sep 11 jQuery
vue中如何动态绑定图片,vue中通过data返回图片路径的方法
Feb 07 Javascript
在vue里使用codemirror遇到的问题
Nov 01 Javascript
深入理解使用Vue实现Context-Menu的思考与总结
Mar 09 Javascript
微信小程序自定义弹窗滚动与页面滚动冲突的解决方法
Jul 16 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
Jan 21 Javascript
javascript中导出与导入实现模块化管理教程
Dec 03 Javascript
详解为什么Vue中的v-if和v-for不建议一起用
Jan 13 Vue.js
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
phpstrom使用xdebug配置方法
2013/12/17 PHP
php检测文件编码的方法示例
2014/04/25 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
2014/07/04 PHP
CodeIgniter删除和设置Cookie的方法
2015/04/07 PHP
最准确的php截取字符串长度函数
2015/10/29 PHP
Laravel 已登陆用户再次查看登陆页面的自动跳转设置方法
2019/09/30 PHP
[IE&amp;FireFox兼容]JS对select操作
2007/01/07 Javascript
jQuery事件之键盘事件(ctrl+Enter回车键提交表单等)
2014/05/11 Javascript
javascript搜索框点击文字消失失焦时文本出现
2014/09/18 Javascript
使用jQuery实现返回顶部
2015/01/26 Javascript
javascript单例模式的简单实现方法
2015/07/25 Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
2016/02/17 Javascript
js+css实现select的美化效果
2016/03/24 Javascript
jquery插件uploadify多图上传功能实现代码
2016/08/12 Javascript
DOM 事件的深入浅出(一)
2016/12/05 Javascript
详解vue slot插槽的使用方法
2017/06/13 Javascript
浅谈Koa服务限流方法实践
2017/10/23 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
vue-cli3跨域配置的简单方法
2019/09/06 Javascript
vue实现学生信息管理系统
2020/05/30 Javascript
vue 将多个过滤器封装到一个文件中的代码详解
2020/09/05 Javascript
Python操作Excel之xlsx文件
2017/03/24 Python
django ajax json的实例代码
2018/05/29 Python
Python中安装easy_install的方法
2018/11/18 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
2019/01/15 Python
css3实现垂直下拉动画菜单示例
2014/04/22 HTML / CSS
英国自行车商店:AW Cycles
2021/02/24 全球购物
数据库的约束含义
2012/09/09 面试题
怎么写有吸引力的自荐信
2013/11/17 职场文书
演讲比赛获奖感言
2014/02/02 职场文书
幼儿园家长评语
2014/02/10 职场文书
《北大荒的秋天》教学反思
2014/04/14 职场文书
做一个有道德的人活动方案
2014/08/25 职场文书
士兵突击观后感
2015/06/16 职场文书
2015年学校管理工作总结
2015/07/20 职场文书
HTML CSS 一个标签实现带动画的抖音LOGO
2022/04/26 HTML / CSS