浅谈angular.js中实现双向绑定的方法$watch $digest $apply


Posted in Javascript onOctober 14, 2015

Angular.js 中的特性,双向绑定.

多么神奇的功能,让视图的改变直接反应到数据中,数据的改变又实时的通知到视图,如何做到的?

这要归功于 scope 下面3个重要的方法:

$watch
$digest
$apply

他们的区别是什么,我们来介绍下:

$watch
这是一个监听 scope 上数据的监听器

方法说明:

$scope.$watch('参数',function(newValue,oldValue){
 //逻辑处理
})

上面我们就是创建了一个监听器.
‘参数' 就是$scope对象下的一个对象(或者一个对象的属性),注意,这里是字符串形式.

假如你要监听 $scope.name 属性.

$scope.$watch('name',function(newValue,oldValue){
 //逻辑处理
})

如上代码, ‘name' 需要引号

参数后面跟着回调函数,回调函数参数返回了被监听 属性,变化后的新值,以前变化前的旧值.

$digest

他负责检查 scope 中的数据是否发生了变化,如果某个属性有变化,马上会通知此属性的监听器 ($watch 注册的监听器),触发监听器,执行回调函数.

$apply

这个方法和 $digest 很相似, $digest 检查scope 中的所有数据
$apply 相当于检查 rootScope 中的所有数据,他会从父级到子级来检查所有数据

$apply() == $rootScope.$digest()

$apply() 方法有两种形式.

第一种 接受一个 function作为参数.
这样触发 $digest 函数并且执行一次 参数中的 function

第二种  不接受任何参数.
这样只是触发一轮 $digest 父级到子级的循环

Angular.js 中一班不会直接调用 $digest ,而是用 $scope.$apply() 来代替

我没有设定监视器,为什么视图和数据可以双向绑定

比如一个文本框 ng-model="name"
这时其实 $scope 对象下已经有了一个属性 name 来对应和 上面的视图进行双向绑定

如何实现的?

其实,当我们定义 ng-model="name"  或者 ng-bind="name" 或者 {{name}}
这时 angular.js 会在 $scope 模型上自动为 “name” 属性设置一个监听器:

$scope.$watch('name', function(newValue, oldValue) {
  //监听 name 属性的变化
});

原来这里 angular.js 帮我们自动创建了一个监听器,所以此属性和 $scope.name 数据才会实时的双向绑定.

当然,有时候你也会发现明明数据变化了.但是UI 没有刷新,是双向绑定失效了吗?

没有

只是在 $scope 模型遍历 digest 循环时,你的数据还没有返回来,

比如异步调用方法,callbac 返回的数据
比如你在 setTimeout 设置了定时触发函数,然后修改模型数据
总之,是错过了 $scope 模型的 digest 循环,导致模型没有通知UI去根据新数据刷新.

遇到这样的问题怎么办?

我们只好自己去手动调用 digest来循环检查一次数据.实现双向绑定

上面我们已经说过,通常不要去直接调用 digest 方法,而是手动调用 $apply 方法,间接实现触发 $digest 循环.

如下:

setTimeout(function() {
 $scope.name= '一介布衣';
 $scope.$apply();
}, 2000);

问题来了,上面时候该去手动调用 apply 方法

目前为止, angular.js 为一部分指令和服务自动实现了 $apply() 方法.

例如, ng-click ,ng-model ,$timeout服务,$http服务 等

调用后,angular.js 会自动帮我们调用 $apply() 来实现数据双向绑定.

Javascript 相关文章推荐
基于jquery的从一个页面跳转到另一个页面的指定位置的实现代码(带平滑移动的效果)
May 24 Javascript
js获取当月最后一天实例代码
Nov 19 Javascript
浅析IE10兼容性问题(frameset的cols属性)
Jan 03 Javascript
jQuery中的siblings用法实例分析
Dec 24 Javascript
Bootstrap学习笔记之css组件(3)
Jun 07 Javascript
浅谈Cookie的生命周期问题
Aug 02 Javascript
ES6中的数组扩展方法
Aug 26 Javascript
JavaScript实现QQ列表展开收缩扩展功能
Oct 30 Javascript
zTree节点文字过多的处理方法
Nov 24 Javascript
详解webpack编译多页面vue项目的配置问题
Dec 11 Javascript
详解vue中使用protobuf踩坑记
May 07 Javascript
JavaScript执行机制详细介绍
Dec 06 Javascript
JS更改select内option属性的方法
Oct 14 #Javascript
JavaScript+CSS实现仿Mootools竖排弹性动画菜单效果
Oct 14 #Javascript
JS实现的最简Table选项卡效果
Oct 14 #Javascript
JS仿淘宝实现的简单滑动门效果代码
Oct 14 #Javascript
JavaScript实现的伸展收缩型菜单代码
Oct 14 #Javascript
smartcrop.js智能图片裁剪库
Oct 14 #Javascript
深入学习JavaScript对象
Oct 13 #Javascript
You might like
php函数的常用方法及注意之处小结
2011/07/10 PHP
浅析Mysql 数据回滚错误的解决方法
2013/08/05 PHP
php实现的验证码文件类实例
2015/06/18 PHP
js代码实现微博导航栏
2015/07/30 PHP
php数值转换时间及时间转换数值用法示例
2017/05/18 PHP
javascript textContent与innerText的异同分析
2010/10/22 Javascript
解析javascript 数组以及json元素的添加删除
2013/06/26 Javascript
js中widow.open()方法使用详解
2013/07/30 Javascript
js正则表达式验证邮件地址
2015/11/12 Javascript
详解JavaScript逻辑And运算符
2015/12/04 Javascript
详解AngularJS中的http拦截
2016/02/09 Javascript
js HTML5手机刮刮乐代码
2020/09/29 Javascript
jquery事件与绑定事件
2017/03/16 Javascript
elementui之el-tebs浏览器卡死的问题和使用报错未注册问题
2019/07/06 Javascript
layui+SSM的数据表的增删改实例(利用弹框添加、修改)
2019/09/27 Javascript
nodeJs的安装与npm全局环境变量的配置详解
2020/01/06 NodeJs
JavaScript监听键盘事件代码实现
2020/06/03 Javascript
小程序选项卡以及swiper套用(跨页面)
2020/06/19 Javascript
在Vue中使用CSS3实现内容无缝滚动的示例代码
2020/11/27 Vue.js
[01:11:21]DOTA2-DPC中国联赛 正赛 VG vs Elephant BO3 第一场 3月6日
2021/03/11 DOTA
Python os模块介绍
2014/11/30 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
2019/01/15 Python
python-序列解包(对可迭代元素的快速取值方法)
2019/08/24 Python
keras做CNN的训练误差loss的下降操作
2020/06/22 Python
Python pymsql模块的使用
2020/09/07 Python
纯CSS3打造属于自己的“小黄人”
2016/03/14 HTML / CSS
canvas 阴影和图形变换的示例代码
2018/01/02 HTML / CSS
什么是lambda函数
2013/09/17 面试题
应届生学校辅导员求职信
2013/11/07 职场文书
农村婚礼证婚词
2014/01/10 职场文书
统计学教授推荐信
2014/09/18 职场文书
2015年客房服务员工作总结
2015/05/15 职场文书
2019年思想汇报
2019/06/20 职场文书
Java面试题冲刺第十九天--数据库(4)
2021/08/07 Java/Android
spring cloud 配置中心native配置方式
2021/09/25 Java/Android