浅谈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 相关文章推荐
防止xss和sql注入:JS特殊字符过滤正则
Apr 18 Javascript
js获取或设置当前窗口url参数的小例子
Oct 14 Javascript
JavaScript获取文本框内选中文本的方法
Feb 20 Javascript
javascript组合使用构造函数模式和原型模式实例
Jun 04 Javascript
基于jquery实现在线选座订座之影院篇
Aug 24 Javascript
vue开发心得和技巧分享
Oct 27 Javascript
Javascript blur与click冲突解决办法
Jan 09 Javascript
ionic实现下拉刷新载入数据功能
May 11 Javascript
jQuery实现可拖动进度条实例代码
Jun 21 jQuery
JS原生轮播图的简单实现(推荐)
Jul 22 Javascript
vue中引用swiper轮播插件的教程详解
Aug 16 Javascript
微信小程序中wxs文件的一些妙用分享
Feb 18 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
解决控件遮挡问题:关于有窗口元素和无窗口元素
2007/01/28 PHP
php的dl函数用法实例
2014/11/06 PHP
PHP内存缓存Memcached类实例
2014/12/08 PHP
javascript 动态table添加colspan\rowspan 参数的方法
2009/07/25 Javascript
用JQUERY增删元素的代码
2012/02/14 Javascript
js中的onchange和onpropertychange (onchange无效的解决方法)
2014/03/08 Javascript
jquery默认校验规则整理
2014/03/24 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
jQuery选择器基础入门教程
2016/05/10 Javascript
jQuery+HTML5实现弹出创意搜索框层
2016/12/29 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
浅谈原生JS实现jQuery的animate()动画示例
2017/03/08 Javascript
React Native 使用Fetch发送网络请求的示例代码
2017/12/02 Javascript
6行代码实现微信小程序页面返回顶部效果
2018/12/28 Javascript
微信小程序 Storage更新详解
2019/07/16 Javascript
JSONObject与JSONArray使用方法解析
2020/09/28 Javascript
Python获取服务器信息的最简单实现方法
2015/03/05 Python
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
python使用PyGame绘制图像并保存为图片文件的方法
2015/04/24 Python
pytorch 利用lstm做mnist手写数字识别分类的实例
2020/01/10 Python
详解python常用命令行选项与环境变量
2020/02/20 Python
详解Python多线程下的list
2020/07/03 Python
如何基于Python实现word文档重新排版
2020/09/29 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
电影T恤、80年代T恤和80年代服装:TV Store Online
2020/01/05 全球购物
一套VC试题
2015/01/23 面试题
园林技术个人的自我评价
2014/02/15 职场文书
如何写自我评价?自我评价写什么好?
2014/03/14 职场文书
医院院务公开实施方案
2014/05/03 职场文书
会计电算化专业求职信
2014/06/10 职场文书
日语专业毕业生自荐书
2014/06/18 职场文书
ktv周年庆活动方案
2014/08/18 职场文书
关于随地扔垃圾的检讨书
2014/09/30 职场文书
2015年学校政教工作总结
2015/07/20 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
Pandas实现批量拆分与合并Excel的示例代码
2022/05/30 Python