当前位置: 首页 > news >正文

Angular数据绑定机制

关键词:$watch, $digest, $apply, dirty-checking

1.Angular.js扩展浏览器的事件循环

浏览器持续等待例如用户交互这样的事件。当你在一个<input>标签里输入字符之后,这个事件的回调函数在JS解释器中执行了其包含的DOM操作,执行完毕后,浏览器响应地对DOM做出了变化。Angular拓展了这个事件循环,使它有时候成为angular context 的执行环境。

2.$watch list

$watch 可以检测model的变化。每当绑定一个数据到view上的时候,$watch队列就会插入一条对应的$watch。例子如下:

  • controller.js:
app.controller('MainCtrl', function($scope) {
  $scope.people = [...]; // 假设长度为10
});
  • index.html:
<ul>
  <li ng-repeat="person in people">
      {{person.name}} - {{person.age}}
  </li>
</ul>

其中ng-repeat 生成了一个1个$watch,每个person生成了2个$watch,总共是(1+2*10),21个$watch$watch的生成阶段是模板加载完成,也就是linking阶段。(angular分为compilelinking阶段),Angular会寻找每个directive(上面的例子中ng-repeat和{{}}都属于directive),然后生成每个$watch

3.$digest 循环

当浏览器接收到angular context相关的事件时,$digest循环就会被触发。它由2个小循环组成,1个处理evalAsync 队列,另一个处理$watch队列。$digest进行循环时,将遍历$watch队列,查看是否有数据更新过,这种遍历就叫做dirty-checkin(脏检查),如果脏检查发现有$watch更新,将会触发新的脏检查,直到所有的$watch都没有更新。这样就能保证每个model都不会变化。

脏检查超过10次后会抛出异常防止无限循环。$digest循环结束后DOM会相应地发生变化。其实$digest从字面意义理解就像“消化”的过程一样,逐渐地把所有营养($watch的变化)都吸收掉。

4.通过$apply 进入 angular context

$apply 决定事件是否进入angular context,使用angualr的自带directive,比如ng-model,更改绑定的数据时,angular会将事件封装到$apply中。比如,ng-model="name"的输入框,输入字符“w”,事件会调用,$apply("name='w';"),完成$scope中的数据更新。
调用第三方库时的数据绑定
当在angular中调用jquery,并不能更新jquery绑定的数据,因为jquery没有调用$apply,事件没有进入angular context,导致$digest没有执行。例子如下:

  • app.js
  app.directive('clickable', function() {
    return {
      restrict: "E",
      scope: {
        count1: '=',
        count2: '='
      },
      template: '<ul style="background-color: lightblue"><li>{{count1}}</li><li>{{count2}}</li></ul>',
      link: function(scope, element, attrs) {
        element.bind('click', function() {
          scope.count1++;
          scope.count2++;
        });
      }
    }
});
app.controller('MainCtrl', function($scope) {
  $scope.count1= 0;
  $scope.count2= 0;
});

例子中,每次点击该元素,预期count1和count2都会自增1,但实际没有。其实$scope(ViewModel)已经改变,但是没有强制执行$digest。修改click事件如下:

element.bind('click', function() {
  scope.$apply(function() {
      scope.foo++;
      scope.bar++;
  });
})

经过调用$apply实现了预期。

5.总结

angular事件绑定机制如下图:

图片描述

相关文章:

  • Java 中的E,K,V,T,U,S
  • 订阅Forge Viewer所有的事件
  • 使用正则表达式,取得点击次数,函数抽离
  • 记一次和乔布斯合作最难忘的经历
  • 第9章WEB09-Servlet篇
  • servlet匹配路径时/和/*的区别(转)
  • POJ 2251 Dungeon Master
  • 面试总结JavaScript篇
  • Generic detail view PostDetailView must be called with either an object pk or a slug.解决
  • 高端家电“金选奖”名单揭晓,激起新消费主义浪潮
  • Python2与Python3的区别
  • 集群中用Memcached来实现session共享
  • AngularJs的表单验证
  • 如何查看linux中的ssh端口开启状态
  • Go 语言之 struct 结构体
  • CSS居中完全指南——构建CSS居中决策树
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Electron入门介绍
  • FastReport在线报表设计器工作原理
  • Js基础——数据类型之Null和Undefined
  • js算法-归并排序(merge_sort)
  • MobX
  • react 代码优化(一) ——事件处理
  • 猴子数据域名防封接口降低小说被封的风险
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 如何学习JavaEE,项目又该如何做?
  • 数据科学 第 3 章 11 字符串处理
  • 一些关于Rust在2019年的思考
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • 数据可视化之下发图实践
  • ​一些不规范的GTID使用场景
  • #每日一题合集#牛客JZ23-JZ33
  • (4.10~4.16)
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (多级缓存)缓存同步
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (十)c52学习之旅-定时器实验
  • (数据结构)顺序表的定义
  • (推荐)叮当——中文语音对话机器人
  • (转)shell调试方法
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .htaccess 强制https 单独排除某个目录
  • .libPaths()设置包加载目录
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .Net各种迷惑命名解释
  • ::什么意思
  • :如何用SQL脚本保存存储过程返回的结果集
  • @AutoConfigurationPackage的使用