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. w10系统老是自动息屏_大师解答win10系统无法自动关屏/待机和睡眠的恢复教程
  2. FPGA之道(80)静态时序分析(六)常用时序约束介绍(基于ISE的UCF文件语法)
  3. oracle变量绑定代码,Oracle 绑定变量
  4. 不愿意和别人打交道_参加完孩子学校的运动会,宝妈吐槽贫富圈子差距大,不适合打交道...
  5. php 获取一年的月份_php 根据日期获取星座
  6. webpack4.0各个击破(7)—— plugin篇
  7. 通信网真的面临容量危机?
  8. Docker封装Java环境镜像(Alpine+OpenJDK)
  9. 博客开通了-里面有秘密哦
  10. HTML常用标签超详细整理
  11. Win7开机加速全攻略一:序章和开机原理
  12. 制作文字水印图片、图片水印
  13. 阿里云安全组已经开放端口但是服务器端口还是不能访问
  14. 一个奇怪的方法解决华为ENSP模拟器路由器启动后命令行一直“#”的问题
  15. win7设置定时锁定计算机,Win7系统怎么设置锁屏?Win7系统设置电脑锁屏的方法
  16. [Go]获取当前时间戳秒/毫秒/纳秒 转成字符串string
  17. 国际标准化组织(Iso)对质量(Quality)的定义
  18. 右手螺旋判断磁感应强度方向_高中物理电流磁场的判断方法是什么?叉乘方向右手螺旋定则如何运用...
  19. Vue进阶(贰零柒):Webpack 性能优化措施汇总
  20. 谷歌浏览器夜间模式切换

热门文章

  1. PTA 7-6 列车调度
  2. 华南农业大学C语言程序设计(实验八)
  3. IDEA如何全局替换变量
  4. html中input只读属性readonly 和 disable的区别
  5. 黑马程序员MySQL数据库之基础篇笔记(SQL语法)(每日更新)
  6. 国外APP项目的上线流程
  7. Compute Goes Brrr:重温强化学习之父Sutton关于AI的70年惨痛教训
  8. 最新WordPress全开源艺术主题Artblog模板
  9. 一次骑车回家突发奇想的复盘
  10. OpenJudge P4124海贼王之伟大航路