写在前面

  双向绑定是angular的大亮点,然后支撑它的就是脏检测。一直对脏检测都有一些理解,却没有比较系统的概念。

  以下是我阅读网上博文以及angular高级程序设计的理解与总结。

  接收指导与批评。

脏检查:

  将原对象赋值一份快照。在某个时间,遍历比较这个对象和快照(新旧值),如果不一样就执行执行某些操作。

angular中的脏检查:

  1.不会检查所有的对象。当对象被绑定到html会检查,手动$scope.$watch()的会检查。检查的手段就是为这些对象创建(watcher)对象。并push到(watcher队列) 2.不会检查所有的属性。只要被绑定的属性才会被注册。 在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了N个属性,就会添加N个watcher。

angular注册watcher对象

  angualr会为每一个绑定到DOM的对象/对象的属性,创建一个watcher对象,(使用$scope.$watch()方法也会创建),watcher对象有好几个属性,(下面是笔者理解抽象出来的,并不是真的属性名

watch = {
name:'', //当前的watch 对象 观测的数据名,锁定监听的是什么
getNewValue:function($scope){ //获取监听属性的最新值
...
return newValue;
},
listener:function(newValue,oldValue){ // 先比较新值与旧值判断是否继续执行,一般负责使用新值更新DOM页面,也可以是$watch方法注册的回调函数
...
}
}

  $$watchers的watcher属性截图

$scope.$$watchers队列

  每一个创建好的watcher对象会被push到各自的controller作用域的$scope.$$watchers队列里面。
  脏检测就是遍历watchers的过程。

脏检测通过两个方法触发:$digest(), $apply()
  $digest:是遍历当前作用域以及其子作用域的$$watchers队列,并执行其listener。
  $apply:是对$digest()的封装。接受一个函数参数(包含脱离angular环境的逻辑,需要却不会自己触发脏检测, 所以$apply帮他触发一下。),$apply在执行了参数函数之后自动调用 $rootScope.$digest (就是从更作用于开始遍历每一个$scope.$$watchers队列)

  如果你对自己的逻辑比较清楚,可以不使用$apply,改用$scope.$digest(),只遍历当前与其子作用域。不用从rootScope开始

  如果不是很了解逻辑,建议还是使用$apply()从rootScope开始,避免需要更新的值没有被更新,并且$apply会把参数函数放在try...catch里面,如果逻辑发生错误。会把错误传给$exceptionHandler service来处理。

$scope.data = ;
$scope.data2 = ;
// code 1
setInterval(function() {
$scope.$apply(function() {
$scope.data++;
console.log('first:', $scope.data)
});
}, ); // code 2
setInterval(function() {
$scope.data2++;
console.log('second:', $scope.data2)
$scope.$apply(); // 对比code1,少了try...catch
// $scope.$digest(); // 只遍历当前及其子作用域的$$watchers队列
},)

一次脏检测中$digest()执行的次数?

  在一个脏检测中,digest至少会执行两次

  因为某一个监听属性的listener可能会改变另一个监听属性的值。因此,angular需要在一次$digest()之后判断这一轮digest中时候有没有属性发生变化并执行了listener,如果有,angular必须再次调用$digest();当已经连续触发了10次$digest(),若还有属性发生变化,angular就会认为你的逻辑错了并console报告。因此在$scope.$watch时要自己多加注意理解好逻辑问题。

什么时候会触发脏检测?

  好像不少人有一个误区。angular是定时执行脏检测的!!!!(我之前还问过,angular设置多久执行一次脏检测,无言以对)

  angular并不是定时的。会触发脏检测的有以下:

    1. controller 初始化
    2. 几乎所有ng-开头的事件(ng-click,ng-change...)
    3. http请求
    4. $timeout,$interval
    5. 手动调用$apply(), $digest()

  回头想想,如果是定时的,怎么会有脱离angualr环境的说法呢?

angular1.x 脏检测的更多相关文章

  1. 详解angular2组件中的变化检测机制(对比angular1的脏检测)

    组件和变化检测器 如你所知,Angular 2 应用程序是一颗组件树,而每个组件都有自己的变化检测器,这意味着应用程序也是一颗变化检测器树.顺便说一句,你可能会想.是由谁来生成变化检测器?这是个好问题 ...

  2. 我的angularjs源码学习之旅3——脏检测与数据双向绑定

    前言 为了后面描述方便,我们将保存模块的对象modules叫做模块缓存.我们跟踪的例子如下 <div ng-app="myApp" ng-controller='myCtrl ...

  3. js 脏检测

    参考 基础知识 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  4. 迈向angularjs2系列(4):脏值检测机制

    目录 一: 概念简介 脏值检测,简单的说就是在MVC的构架中,视图会通过模型的change事件来更新自己. 脏值检测的核心代码是观察者模式的实现,其机制会执行digest循环,在特定UI组件的上下文执 ...

  5. Angularjs 脏值检测

    文章转自:http://www.ituring.com.cn/article/39865 构建自己的AngularJS,第一部分:Scope和Digest 原文链接:http://teropa.inf ...

  6. AngularJS 脏检查深入分析

    写在开头 关于Angular脏检查,之前没有仔细学习,只是旁听道说,Angular 会定时的进行周期性数据检查,将前台和后台数据进行比较,所以非常损耗性能. 这是大错而特错的.我甚至在新浪前端面试的时 ...

  7. AngularJS 脏检查机制

    脏检查是AngularJS的核心机制之一,它是实现双向绑定.MVVM模式的重要基础. 一.digest循环 AngularJS将双向绑定转换为一个堆watch表达式,然后递归检查这些watch表达式的 ...

  8. [转贴]有关Angular 2.0的一切

    对Angular 2.0的策略有疑问吗?就在这里提吧.在接下来的这篇文章里,我会解释Angular 2.0的主要特性区域,以及每个变化背后的动机.每个部分之后,我将提供自己在设计过程中的意见和见解,包 ...

  9. Angular React 和 Vue的比较

    Angular(1&2),React,Vue对比 一 数据流 数据绑定 Angular 使用双向绑定即:界面的操作能实时反映到数据,数据的变更能实时展现到界面. 实现原理: $scope变量中 ...

随机推荐

  1. 一些小bug

    1.ie6-ie8中是不支持的,需要加上下面这句话: filter: progid:DXImageTransform.Microsoft.Alpha(opacity=70);   2.去除虚线框 a  ...

  2. Android项目---LayoutParams

    LinearLayout.LayoutParams extends ViewGroup.MarginLayoutParams java.lang.Object    ↳ android.view.Vi ...

  3. QTP特点有哪些?

    QTP特点有哪些? 浏览:77 | 更新:2013-06-19 12:35 QTP是一个侧重于功能的回归自动化测试工具:提供了很多插件,如:.NET的,Java的,SAP的,Terminal Emul ...

  4. js实现多张图片同时放大缩小相对位置不变

    项目要求需要用js实现同时放大多张图片相对位置不变,就和同事去一家国外网站的js文件中跟踪扒取了这一算法, 庆幸的是算法抠出来了并整理了出来,但遗憾的只知计算过程却弄不明白算法原理: 大体上是核心运算 ...

  5. MVC之前的那点事儿系列进入CLR

    MVC之前的那点事儿系列(1):进入CLR MVC之前的那点事儿系列,是笔者在2012年初阅读MVC3源码的时候整理的,主要讲述的是从HTTP请求道进入MVCHandler之前的内容,包括了原创,翻译 ...

  6. DropDownListFor的用法

    Asp.Net MVC中DropDownListFor的用法   在Asp.Net MVC中可以用DropDownListFor的方式来让用户选择已定列表中的一个数值.用法不复杂,这里简单做一个记录. ...

  7. c#拷贝

    话谈c#拷贝 c#中类型分为值类型和引用类型,值类型对象赋值是本身就是赋的自身的一个副本,而引用类型赋值时则赋的是指向堆上的内存,假如我们不想赋这个地址而想将对象赋过去要怎么做呢?首先要知道拷贝分为浅 ...

  8. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

  9. 第一章 CLR 的执行模型

    CLR via C# 读书笔记:第一章 CLR 的执行模型(1) 第Ⅰ部分CLR基础.这部分为三章(第一章:CLR的只想能够模型,第二章:生成.打包.部署和管理应用程序及类型,第三章:共享程序集和强命 ...

  10. html页面显示服务器时间

    全局变量 var lblTimer; var d; ready事件里面写 lblTimer = $("#lbltimer"); d = new Date('<%=DateTi ...