浅谈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 oLoader实现的加载图片和页面效果
Mar 14 Javascript
JavaScript实现按照指定长度为数字前面补零输出的方法
Mar 19 Javascript
JavaScript如何自定义trim方法
Jul 28 Javascript
JS实现的简洁二级导航菜单雏形效果
Oct 13 Javascript
基于javascript制作微博发布栏效果
Apr 04 Javascript
JQuery的常用选择器、过滤器、方法全面介绍
May 25 Javascript
如何处理JSON中的特殊字符
Nov 30 Javascript
vue组件生命周期详解
Nov 07 Javascript
浅谈React组件之性能优化
Mar 02 Javascript
JavaScript this在函数中的指向及实例详解
Oct 14 Javascript
Vue2.x和Vue3.x的双向绑定原理详解
Nov 05 Javascript
利用JavaScript写一个简单计算器
Nov 27 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 Static关键字实用方法
2010/06/04 PHP
Yii2实现增删改查后留在当前页的方法详解
2017/01/13 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
去除链接虚线全面分析总结
2006/08/15 Javascript
JavaScript高级程序设计(第3版)学习笔记8 js函数(中)
2012/10/11 Javascript
js的toUpperCase方法用法实例
2015/01/27 Javascript
分享jQuery网页元素拖拽插件
2020/12/01 Javascript
JavaScript使用原型和原型链实现对象继承的方法详解
2017/04/05 Javascript
js仿微信公众平台打标签功能
2017/04/08 Javascript
深入浅出webpack之externals的使用
2017/12/04 Javascript
webstorm和.vue中es6语法报错的解决方法
2018/05/08 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
2018/07/07 Javascript
解决layui laydate 时间控件一闪而过的问题
2019/09/28 Javascript
js+canvas实现五子棋小游戏
2020/08/02 Javascript
Python3.x和Python2.x的区别介绍
2013/02/12 Python
使用Python进行二进制文件读写的简单方法(推荐)
2016/09/12 Python
Python爬虫实现验证码登录代码实例
2019/05/10 Python
win8.1安装Python 2.7版环境图文详解
2019/07/01 Python
如何通过Python实现标签云算法
2019/07/02 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
2019/08/05 Python
使用python实现回文数的四种方法小结
2019/11/24 Python
Python写出新冠状病毒确诊人数地图的方法
2020/02/12 Python
python3.6.5基于kerberos认证的hive和hdfs连接调用方式
2020/06/06 Python
Python之字典添加元素的几种方法
2020/09/30 Python
纯CSS改变webkit内核浏览器的滚动条样式
2014/04/17 HTML / CSS
html5基础标签(html5视频标签 html5新标签用法)
2013/12/30 HTML / CSS
英国最大的天然和有机产品在线零售商之一:Big Green Smile
2020/05/06 全球购物
linux面试题参考答案(11)
2012/05/01 面试题
大专计算机个人求职的自我评价
2013/10/21 职场文书
精细化工应届生求职信
2013/11/17 职场文书
2014年高一班主任工作总结
2014/12/05 职场文书
个人汇报材料范文
2014/12/30 职场文书
党员干部公开承诺书范文
2015/04/27 职场文书
2016年小学生教师节广播稿
2015/12/18 职场文书
初二物理教学反思
2016/02/19 职场文书
2016年大学生暑期社会实践活动总结
2016/04/06 职场文书