angularjs的双向数据绑定

脏值(发生了变化的值)检查不等于定时轮询,而是特定事件触发才会执行
只有指定事件触发后才会进入脏值轮询。
- DOM事件,譬如用户输入文本,点击按钮等。(ng-click)
- XHR(ajax)响应事件 (http)−浏览器Location变更事件(http) - 浏览器Location变更事件 (location)
- Timer事件(timeout,timeout, interval)
- 执行digest()或digest()或apply()

$digest函数的作用是调用这个监控函数,并且比较它返回的值和上一次返回值的差异。如果不相同,监听器就是脏的,它的监听函数就应当被调用。

$digest$apply

  • 在Angular中,有apply和apply和digest两个函数.

  • apply是apply 是 scope(或者是 direcvie 里的 link 函数中的 scope)的一个函数,调用它会强制一次 digest循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行digest 循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行 apply 的标志)。

差异

$apply可以带参数,它可以接受一个函数,然后在应用数据之后,调用这个函数。所以,一般在集成非Angular框架的代码时,可以把代码写在这个里面调用。

当调用 digest的时候,只触发当前作用域和它的子作用域上的监控,但是当调用digest 的时候,只触发当前作用域和它的子作用域上的监控,但是当调用 apply 的时候,会触发作用域树上的所有监控

原理

双向数据绑定意味着当 view 中有任何数据发生变化会自动地反馈到 scope 的数据上,当 scope 模型发生变化时,view 中的数据也会更新到最新的值。

AngularJS 确实在幕后为 scope 模型上设置了一个 监听队列,用来监听数据变化并更新 view 。

每次绑定一个东西到 view 上时 AngularJS 就会往 watch队列里插入一条watch 队列里插入一条 watch,用来检测它监视的 model 里是否有变化的东西。

以一次click操作执行的监听为例:
- 按下按钮
- 浏览器接收到一个事件,进入 angular context
- digest循环开始执行,查询每个digest 循环开始执行,查询每个 watch 是否变化
- 由于监视 scope.val的scope.val 的 watch 报告了变化,它会强制再执行一次 digest循环。−新的digest 循环。 - 新的 digest 循环没有检测到变化。
- 浏览器拿回控制权,更新与 $scope.val 新值相应部分的 DOM 。

digest循环会持续运行直到model不再发生变化,或者digest 循环会持续运行直到 model 不再发生变化,或者 digest 循环的次数达到了一定阈值(抛出异常防止无限循环)。

代码示例(重点)

  • 使用了 JavaScript 中的 setTimeout() 来更新一个 scope model

  • 用指令设置一个 DOM 事件 listener 并且在该 listener 中修改了一些 models

页面中绑定的message值不会刷新。

$scope.setMsg = function() {  setTimeout(function() {  $scope.message = 'hello world';  console.log('message:' + $scope.message);  }, 2000);
}
$scope.setMsg();

要想解决以上问题[message值不实时刷新]有以下三种方法。

1、 直接使用:$scope.$apply();

setTimeout(function() {  $scope.message = 'hello world';  console.log('message:' + $scope.message2);$scope.$apply();
}, 2000);

2、 $scope.$apply(执行相应操作)

$scope.$apply可以替换为$scope.$digest

setTimeout(function() {  $scope.$apply(function() {  $scope.message1 = 'hello world';   console.log('message1:' + $scope.message);  });
}, 2000);

3、 使用angular封装的$timeout

$scope.$apply可以替换为$scope.$digest
- $timeout是angular对于setTimeout的封装,$interval是angular对于setInterval的封装。
- 会自动在内部函数执行完后调用$scope.$apply();(脏值检查)。

$scope.setMsg = function() {  $timeout(function() {  $scope.message2 = 'hello world';  console.log('message2:' + $scope.message2);}, 2000);
} 

注:

  1. 在取message的值时必须在controller作用域内

  2. $timeout需要在控制器中注入后使用

使用$watch监听的潜在坑点

先大致介绍下$watch.
- $scope.$watch()可用于监听变量、数组或对象。有三个参数
- 第一个参数:被监听的对象[必填]
- 第二个参数:监听到变化时执行的函数[必填]
- 第三个参数:布尔值,true意为监听监听对象内容的改变,false意为监听监听对象地址或引用的改变[选填,默认false]
- 要想取消监听只需执行watch函数的返回值(没有理解就看看下边的代码)

var cancelWatch = $scope.$watch('message2', function(newValue, oldValue) {//监听到变化执行的操作
},true);
//取消监听
cancelWatch();

之前一直以为可以用$watch监听到变化以后强制执行$scope.$apply();,直到自己写代码测试才发现这么写会报错。

$scope.setMsg = function() {  setTimeout(function() {  $scope.message2 = 'hello steven';  }, 2000);
}var cancelWatch = $scope.$watch('message2', function(newValue, oldValue) {$scope.$digest();
},true);

报错信息原描述:At any point in time there can be only one $digest or $apply operation in progress. This is to prevent very hard to detect bugs from entering your application. The stack trace of this error allows you to trace the origin of the currently executing $apply or$digest call, which caused the error.

也就是说在任意时刻只能有一个$digest$apply执行操作进行当前当前页面的脏值检查。

  • 初始化程序时监听是开启的
  • 初始化时其实已经通过变量提升改变了$scope.message2(此时相当于定义为了undefined)
  • $watch监听到数据变化提前执行了$scope.$digest(),重复调用监听报错

取消 $timeout

var customTimeout = $timeout(function () {  // your code
}, 1000);$timeout.cancel(customTimeout);

通过编译执行阶段流程理解数据双向绑定

编译阶段:

  • ng-model 和 input 指令 在 标签中设置了一个 keydown 监听器
  • 在{{greeting}} 插值(也就是表达式)这里设置了一个 $watch 来监测 username 的变化

执行阶段:

  • 在 输入框中按下 ‘X’ 键引起浏览器发出一个 keydown 事件
  • input 指令捕捉到输入值的改变调用 $apply(“username = ‘X’;”) 进入Angular的执行环境来更新应用的数据模型
  • Angular将 username = ‘X’; 作用在数据模型之上,这样 scope.username 就被赋值为 ‘X’ 了
  • $digest 轮循开始
  • $watch 列表中监测到 username 有一个变化,然后通知 {{greeting}} 插值表达式,进而更新DOM
  • 执行离开Angular的上下文,进而 keydown 事件结束,然后执行也就退出了 JavaScript的上下文;这样 $digest 完成
  • 浏览器用更新了的值重新渲染视图

END

angularjs双向数据绑定原理解析相关推荐

  1. Vue 的双向数据绑定原理解析

    在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...

  2. vue双向数据绑定原理分析--Mr.Ember

    vue双向数据绑定原理分析 摘要 vue常用,但原理常常不理解,下面我们来具体分析下vue的双向数据绑定原理. (1)创建一个vue对象,实现一个数据监听器observer,对所有数据对象属性进行监听 ...

  3. 双向数据绑定原理(三种实现方式)

    <!DOCTYPE html> <html><head><meta charset="UTF-8"><title>双向数 ...

  4. 请这样回答双向数据绑定原理

    前言 双向数据绑定是Vue的重要原理,也是面试过程中几乎必问的一道题目,搞懂这个原理无论是对我们的技术提高还是对面试都是有百利而无一害的,下面就让我们一起来解决这个问题吧~ 双向数据绑定每一个模块都负 ...

  5. 【Vue的双向数据绑定原理】

    Vue的双向数据绑定原理 先说面试答案: 1. 什么是setter.getter 2. 什么是Object.defineProperty() ? 先简单的实现一个js的双向数据绑定来熟悉一下`Obje ...

  6. 前端面试题 HTML5 CSS3(盒子模型、盒子水平垂直居中、经典布局) JS(闭包、深浅克隆、数据劫持和拦截) 算法(排序、去重、数组扁平化) Vue(双向数据绑定原理、通信方式)

    前端面试题 HTML5 相关面试题 CSS3 相关面试题 盒子模型 盒子水平垂直居中的方案 经典布局方案 圣杯布局 双飞翼布局 flex布局 定位方式布局 css实现三角形 JS 相关面试题 8种数据 ...

  7. vue双向数据绑定原理 1

    1. 原理 1.1 vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布订阅模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化 ...

  8. Vue 双向数据绑定原理

    原理 1.vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布者订阅者模式的方式来实现的,通过Object.defineProperty()来劫持各个属性的 ...

  9. 双向数据绑定原理(Vue)

    双向绑定的底层原理就是应用了发布订阅者模式结合数据劫持,通过Object.defineProperty()方法来劫持各个属性(需要数据绑定的属性,vue 双花括号里面的值就是需要双向数据绑定的属性,如 ...

最新文章

  1. mysql 20小时内_生产环境删除数据库,如何实现在1小时内快速恢复?
  2. Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建
  3. 搜索引擎反作弊之:链接作弊与隐藏作弊
  4. PHP 截取中文字符函数
  5. 金蝶云系统显示服务器离线,金蝶云服务器已离线是什么情况
  6. Struts+Spring+Hibernate练习(完整)
  7. Windows XP系统安装SQL Server 2005(开发版)图解
  8. 天池 在线编程 求和查找
  9. 日常((⊙_⊙)…)
  10. java aqua和metal_Java工具集介绍9_16
  11. linux编程排序,Linux下简单的c编程——选择法排序
  12. 2016-5-31 项目结构调整
  13. typora 有道云笔记_有道云—目前最好用的免费笔记
  14. jquery 点击显示更多
  15. MyBatis学习总结[5]-动态 SQL
  16. Oracle 中文转五笔码
  17. 贝叶斯分析好坏_贝叶斯分析基础——可信度、模型和参数
  18. chrome图片下载插件
  19. jzoj 3837 心灵终结
  20. 类和对象有点东西(一)

热门文章

  1. 系统流程图、数据流图、状态转换图、盒图的区别(软件工程课程中学到的)
  2. bcompare破解
  3. 浦东新区python培训补贴
  4. AI 正在悄悄渗透到我们生活的方方面面
  5. nn.Embedding
  6. 无线充电怎么测试软件,【三星GALAXYNoteII评测】S3能用Note2可以吗?-中关村在线...
  7. 30、今日油价查询API接口,免费好用
  8. 2022年全国职业院校技能大赛试题4(中职组)
  9. DPVO:深度patch视觉里程计(arXiv 2022)
  10. 【财务分析】-----背景+分析方法