脏检查是AngularJS的核心机制之一,它是实现双向绑定、MVVM模式的重要基础。

一、digest循环

  AngularJS将双向绑定转换为一个堆watch表达式,然后递归检查这些watch表达式的结果有没有变化,如果变了,就会执行响应的watcher函数,等到model值不再变化,也就不会再有watcher函数被触发。

  此时,浏览器会重新渲染DOM来体现model的改变,这里所说的watcher函数,是有view上的指令,如ngBind、ngShow、ngHide,或{{}}表达式所注册,它其实是指令在AngularJS的complie阶段会逐一解析、注册。

  AngularJS并不是周期性触发脏检查。只有当view中事件,ajax请求或者 timeout 延迟事件,才会触发脏检查。$scope.$apply是触发脏检查机制的公开接口。我们在封装第三方jQuery插件时,不能自动更新View,需要手动调用$scope.$apply。

二、$watch 对象  

  Angular 每一个绑定到view上的数据,就会有一个 $watch 对象,每当我们将数据绑定到 view上,AngularJS 就会向你的 watchList 上插入一个 $watch对象。这个对象包含三个参数

watch = {
name:'', //当前的watch 对象 观测的数据名
getNewValue:function($scope){ //得到新值
...
return newValue;
},
listener:function(newValue,oldValue){ // 当数据发生改变时需要执行的操作
...
}
}

  getNewValue() 可以得到当前$scope 上的最新值,listener 函数得到新值和旧值并进行一些操作。而常常我们在使用AngularJS的时候,listener 一般都为空,只有当我们需要监测更改事件的时候,才会显示地添加监听。

三、双向数据绑定

  AngularJS实现了双向数据绑定,就是view中的操作能实时反应到viewModel数据,viewModel数据的更改也能在View呈现。view到viewModel数据的更改,是由 vew中绑定的事件,ajax请求,或者tmeout 等回调操作完成,而viewModel数据到view的更新呈现则是由脏检查来做。只有当触发view中的事件,ajax请求或者 timeout 延迟,才会触发脏检查,如用户在文本框里输入了数据,或者ajax取回的新的数据要应用在程序中,或者用户点击了东西需要我们更改一些数据。如果直接使用DOM的onclick方法,数据虽然变更了,但是还没有往View上填充,我们需要在此做一些附加操作。

  双向绑定机制,在DOM操作中,虽然更新了数据的值,但是并没有立即反映到View上,而是通过 apply() 来反映到view上。AngularJS的ng-click 封装了click,然后调用一次 apply 函数,把数据呈现到界面上。在AngularJS 的apply函数中,先进行脏检测,检测 oldValue 和 newVlue 是否相等,如果不相等,将newValue 反馈到界面上,如果通过 $watch 注册了 listener事件,那么就会调用该事件。

四、过程描述

  当接收View上的指令所转发的事件时,就会切换到AngularJS的上下文环境来响应这类事件,digest循环就会触发;遍历一遍所有watcher函数(表达式或对象)称为一轮脏检查,执行完一轮检查,若任一watcher所监听的值改变过,那就重新再进行一次脏检查,知道所有watcher所监听的值都没有变化。

  从第一轮脏检查到结果变得稳定,这是一次digest循环完整过程,当循环结束后,才把变化更新到DOM去,这样可以合并多个更新,防止频繁的DOM操作。

AngularJS 脏检查机制的更多相关文章

  1. 手写AngularJS脏检查机制

    什么是脏检查 View -> Model 浏览器提供有User Event触发事件的API,例如,click,change等 Model -> View 浏览器没有数据监测API. Ang ...

  2. angularjs脏检查

    angularjs实现了双向绑定,与vue的defineProperty不同,它的原理在于它的脏检查机制,以下做了一些总结: angular.js介绍 AngularJs是mvvm框架,它的组件是vm ...

  3. AngularJS 脏检查深入分析

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

  4. angular何时触发脏检查机制

    ng只有在指定事件触发后,才进入$digest cycle: DOM事件,譬如用户输入文本,点击按钮等.(ng-click) XHR响应事件 ($http) 浏览器Location变更事件 ($loc ...

  5. angular2 脏检查机制

    https://www.waitig.com/angular2-%E8%84%8F%E6%A3%80%E6%9F%A5%E8%BF%87%E7%A8%8B.html https://zhuanlan. ...

  6. AngularJs 脏值检查及其相关

    今天突然就想写写$digest和$apply,这些都是脏值检查的主体内容. 先以普通js来做一个简单的监控例子吧: var div = ducoment.getElementById("my ...

  7. Hibernate[延迟加载] [三种状态] [脏检查] [缓存机制]

    一.持久化对象的唯一标识 java中按内存地址不同区分同一个类的不同对象,关系数据库用主键区分同一条记录,Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系 什么是OID? 解析: ...

  8. java对象中的三种状态和脏检查及刷新缓存机制

    瞬时状态 瞬时状态又称临时状态.如果java对象与数据库中的数据没有任何的关联,即此java对象在数据库中没有相关联的记录,此时java对象的状态为瞬时状态,session对于 瞬时状态的ava对象是 ...

  9. angularjs脏机制

    Angular 每一个绑定到UI的数据,就会有一个 $watch 对象. watch = { name:'', //当前的watch 对象 观测的数据名 getNewValue:function($s ...

随机推荐

  1. RTTI(运行时类型识别)

    运行时类型识别(Run-time type identification , RTTI),是指在只有一个指向基类的指针或引用时,确定所指对象的准确类型的操作.其常被说成是C++的四大扩展之一(其他三个 ...

  2. oracle的常用99条语句

    1. select * from emp; 2. select empno, ename, job from emp; 3. select empno 编号, ename 姓名, job 工作 fro ...

  3. 几张图片帮助记忆docker基本原理(转)

    写的非常好的一篇文章,不知道为什么被删除了. 利用Google快照,做个存档. 快照地址:地址 作者地址:青牛 什么是dockerDocker 是一个开源项目,诞生于 2013 年初,最初是 dotC ...

  4. 18 包 ,logging模块使用

    包: 1 什么是包: 包就是一个包含有__init__.py文件的文件夹 宝本质就是一种模块,即包就是用包导入使用的,包内部包含的文件也都是用来被导入使用 2 为什么要用包 包就是文件夹,那文件加就是 ...

  5. linux_域名映射

    vi /etc/hosts在最后加上ip及映射的域名 192.168.229.111 node001 192.168.229.112 node002 192.168.229.113 node003

  6. __getitem__()、__setitem__()与__delitem__()

    # 如果想要运用[]取值,可以实现__getitem__() # 想要运用[]设值,可以实现__setitem__() # 若想通过del与[]来删除,可以实现__delitem__() class ...

  7. hdu6444 2018中国大学生程序设计竞赛 - 网络选拔赛 1007 Neko's loop

    Neko's loop Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total S ...

  8. TCP/IP协议(4):网络层

    网络层上有IP.ICMP.IGMP等协议. 1.IP地址 在OSI模型中,三层网络层负责IP地址,IP数据报帧头中的源地址和目的地址就是指IP地址.IPV4类型IP地址为32位4个字节,IPV6类型I ...

  9. Linux系统下修改环境变量PATH路径

    方法一: PATH=$PATH:/etc/apache/bin 该方法只对当前会话有效,每次注销或者拿出系统,该设置就会无效 方法二: vi /etc/profile 在适当的位置写入:PATH=$P ...

  10. c# radiobutton

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...