浅谈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 相关文章推荐
用JS操作FRAME中的IFRAME及其内容的实现代码
Jul 26 Javascript
jQuery Ajax异步处理Json数据详解
Nov 05 Javascript
jquery.hotkeys监听键盘按下事件keydown插件
May 11 Javascript
javascript实现修改微信分享的标题内容等
Dec 11 Javascript
js判断鼠标左、中、右键哪个被点击的方法
Jan 27 Javascript
Java中Timer的用法详解
Oct 21 Javascript
JavaScript字符串删除重复字符的方法
Dec 25 Javascript
jQuery轻松实现表格的隔行变色和点击行变色的实例代码
May 09 Javascript
关于Bootstrap按钮组件消除黄框的方法
May 19 Javascript
利用Console来Debug的10个高级技巧汇总
Mar 26 Javascript
原生js通过一行代码实现简易轮播图
Jun 05 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
Oct 02 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
Eclipse的PHP插件PHPEclipse安装和使用
2014/07/20 PHP
Codeigniter校验ip地址的方法
2015/03/21 PHP
PHP内部实现打乱字符串顺序函数str_shuffle的方法
2019/02/14 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
tbody元素支持嵌套的注意方法
2007/03/24 Javascript
JQuery EasyUI 数字格式化处理示例
2014/05/05 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
2014/05/28 Javascript
完美兼容各大浏览器的jQuery仿新浪图文淡入淡出间歇滚动特效
2014/11/12 Javascript
javascript正则表达式基础知识入门
2015/04/20 Javascript
jQuery实现手机上输入后隐藏键盘功能
2017/01/04 Javascript
nodejs个人博客开发第七步 后台登陆
2017/04/12 NodeJs
Vue.use()在new Vue() 之前使用的原因浅析
2019/08/26 Javascript
Angular value与ngValue区别详解
2019/11/27 Javascript
理解JavaScript中的对象
2020/08/25 Javascript
[46:55]Ti4 冒泡赛第二轮 LGD vs C9
2014/07/14 DOTA
[20:30]职业巡回赛回顾
2018/08/09 DOTA
python高并发异步服务器核心库forkcore使用方法
2013/11/26 Python
python爬虫入门教程之点点美女图片爬虫代码分享
2014/09/02 Python
Python基于twisted实现简单的web服务器
2014/09/29 Python
利用Python+Java调用Shell脚本时的死锁陷阱详解
2018/01/24 Python
Django框架实现的普通登录案例【使用POST方法】
2019/05/15 Python
Python基本语法之运算符功能与用法详解
2019/10/22 Python
Python PyInstaller库基本使用方法分析
2019/12/12 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
pymongo insert_many 批量插入的实例
2020/12/05 Python
python 第三方库paramiko的常用方式
2021/02/20 Python
CSS3 二级导航菜单的制作的示例
2018/04/02 HTML / CSS
工程建设实施方案
2014/03/14 职场文书
做一个有道德的人活动方案
2014/08/25 职场文书
授权委托书(法人单位用)
2014/09/29 职场文书
全国爱眼日活动总结
2015/02/27 职场文书
拔河比赛新闻稿
2015/07/17 职场文书
MySQL完整性约束的定义与实例教程
2021/05/30 MySQL
JS 基本概念详细介绍
2021/10/16 Javascript
详解PyTorch模型保存与加载
2022/04/28 Python
MySQL新手入门进阶语句汇总
2022/09/23 MySQL