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 插件开发方法小结
Oct 23 Javascript
js中一维数组和二位数组中的几个问题示例说明
Jul 17 Javascript
JS实现判断碰撞的方法
Feb 11 Javascript
js实现星星打分效果的方法
Jul 05 Javascript
使用UrlConnection实现后台模拟http请求的简单实例
Jan 04 Javascript
js获取当前周、上一周、下一周日期
Mar 19 Javascript
iOS + node.js使用Socket.IO框架进行实时通信示例
Apr 14 Javascript
详解Vue爬坑之vuex初识
Jun 14 Javascript
JS 学习总结之正则表达式的懒惰性和贪婪性
Jul 03 Javascript
vue中如何去掉空格的方法实现
Nov 09 Javascript
微信小程序实现复选框效果
Dec 28 Javascript
ES6知识点整理之数组解构和字符串解构的应用示例
Apr 17 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
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
thinkphp3.x中变量的获取和过滤方法详解
2016/05/20 PHP
Yii2 中实现单点登录的方法
2018/03/09 PHP
jquery控制listbox中项的移动并排序
2009/11/12 Javascript
javascript+iframe 实现无刷新载入整页的代码
2010/03/17 Javascript
仿新浪微博登陆邮箱提示效果的js代码
2013/08/02 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
jQuery快速上手:写jQuery与直接写JS的区别详细解析
2013/08/26 Javascript
js获取input长度并根据页面宽度设置其大小及居中对齐
2014/08/22 Javascript
jQuery实现响应浏览器缩放大小并改变背景颜色
2014/10/31 Javascript
跟我学习javascript的undefined与null
2015/11/17 Javascript
微信小程序页面传值实例分析
2017/04/19 Javascript
微信小程序request请求后台接口php的实例详解
2017/09/20 Javascript
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
2017/10/25 Javascript
使用Vue制作图片轮播组件思路详解
2018/03/21 Javascript
如何手动实现es5中的bind方法详解
2018/12/07 Javascript
Vue利用Blob下载原生二进制数组文件
2019/09/25 Javascript
vue实现拖拽进度条
2021/03/01 Vue.js
Python入门_浅谈字符串的分片与索引、字符串的方法
2017/05/16 Python
用Python实现KNN分类算法
2017/12/22 Python
Python yield与实现方法代码分析
2018/02/06 Python
对Django 转发和重定向的实例详解
2019/08/06 Python
Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现
2019/08/13 Python
Python学习笔记之列表推导式实例分析
2019/08/13 Python
python二维键值数组生成转json的例子
2019/12/06 Python
Python写出新冠状病毒确诊人数地图的方法
2020/02/12 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
2021/01/30 Python
CSS3图片旋转特效(360/60/-360度)
2013/10/10 HTML / CSS
英国一家专门出售品牌鞋子的网站:Allsole
2016/08/07 全球购物
学前教育学生自荐信范文
2013/12/31 职场文书
会议邀请书范文
2014/02/02 职场文书
大学毕业自我鉴定范文
2014/02/03 职场文书
五年级科学教学反思
2014/02/05 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
旷课检讨书范文
2015/01/27 职场文书