理解$watch ,$apply 和 $digest --- 理解数据绑定过程
来源:互联网 发布:如何开农村淘宝网店 编辑:程序博客网 时间:2024/06/06 00:21
我们的浏览器一直在等待事件,比如用户交互。假如你点击一个按钮或者在输入框里输入东西,事件的回调函数就会在javascript解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。 Angular拓展了这个事件循环,生成一个angular context
的执行环境(记住,这是个重要的概念),为了解释什么是context
以及它如何工作,我们还需要解释更多的概念
$watch
每次你绑定一些东西到你的UI上时你就会往$watch队列里插入一条$watch
。想象一下$watch
就是那个可以检测它监视的model里时候有变化的东西
index.html
<input ng-model="full_name" type="text" ng-change="changeValue()" placeholder="enter the name" id="myInputId"><p>{{full_name}}</p>
在这里我们有个
$scope.full_name
,它被绑定在了第一个输入框上,然后我们在$watch list
里面加入一个个$watch
:
controllers.js
$scope.full_name = "hello";$scope.changeValue = function () { var myInputElement = document.getElementById("myInputId"); if(myInputElement){ $scope.full_name = myInputElement.value; }};//输入的值发生变化var unregisterWatch = $scope.$watch("full_name",function (newValue,oldValue,scope) { if (newValue===oldValue){ console.log("在监控器初始化阶段运行"); } else{ console.log("$watch"); }},true);因此,每一个绑定到了UI上的数据都会生成一个$watch
。对,那这写$watch
是什么时候生成的呢? 当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段---译者注),Angular解释器会寻找每个directive,然后生成每个需要的$watch
$digest
循环还记得我前面提到的扩展的事件循环吗?当浏览器接收到可以被
angular context
处理的事件时,$digest
循环就会触发。这个循环是由两个更小的循环组合起来的。一个处理evalAsync
队列,另一个处理$watch
队列,这个也是本篇博文的主题。 这个是处理什么的呢?$digest
将会遍历我们的$watch
,然后询问:
- 嘿,
$watch
,你的值是什么?- 是9。
- 好的,它改变过吗?
- 没有,先生。
- (这个变量没变过,那下一个)
- 你呢,你的值是多少?
- 报告,是
full_name
。
- 报告,是
- 刚才改变过没?
- 改变过,刚才是
xxxx
。
- 改变过,刚才是
- (很好,我们有DOM需要更新了)
- 继续询问直到
$watch
队列都检查过。
这就是所谓的dirty-checking
。既然所有的$watch
都检查完了,那就要问了:有没有$watch
更新过?如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch
都没有变化。这样就能够保证每个model都已经不会再变化。记住如果循环超过10次的话,它将会抛出一个异常,防止无限循环。 当$digest
循环结束时,DOM相应地变化
- 我们在文本输入框中输入文本
- 浏览器接收到一个ng-change事件,并在事件中改变full_name的值,然后进入
angular context
。 $digest
循环开始执行,查询每个$watch
是否变化。- 由于监视
$scope.full_name
的$watch
报告了变化,它会强制再执行一次$digest
循环。 - 新的
$digest
循环检测到变化。 - 当循环检测到变化,在这里我们可以使用$watch来监视自己的东西
- 浏览器拿回控制权,更新与
$scope.full_name
新值相应部分的DOM。
这里很重要的(也是许多人的很蛋疼的地方)是每一个进入angular context
的事件都会执行一个$digest
循环,也就是说每次我们输入一个字母循环都会检查整个页面的所有$watch
通过$apply
来进入angular context
谁决定什么事件进入angular context
,而哪些又不进入呢?$apply
!
如果当事件触发时,你调用$apply
,它会进入angular context
,如果没有调用就不会进入。现在你可能会问:刚才的例子里我也没有调用$apply
啊,为什么?Angular为了做了!因此你输入值并且调用ng-change时,事件就会自动被封装到一个$apply
。如果你有一个ng-model="full_name"
的输入框,然后你敲一个f
,事件就会这样调用$apply("full_name = 'f';")
。
Angular什么时候不会自动为我们$apply
呢?
setTimeout(function () { $scope.full_name ="Timeout called!"; // AngularJS unaware of update to $scope}, 2000);
angular就不会自动为我们调用$apply();这个时候需要我们手动调用$apply()去更新我们的作用域对象属性 进而进行$digest
如下:
setTimeout(function () {$apply(function(){$scope.full_name ="Timeout called!"; // AngularJS ware of update to $scope})}, 2000);
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- 补充——理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- angualr-$apply,$digest,$watch的理解
- watch(),$digest()和$apply()
- HTML 再学习
- 【南阳1261】河南多校训练
- bzoj1827(树形dp)
- VCS的 -ntb_opts 的问题
- 关于安装cocoapods遇到的一些坑(ERROR: Error installing cocoapods: activesupport requires Ruby version >= 2.2)
- 理解$watch ,$apply 和 $digest --- 理解数据绑定过程
- Bubble Sort
- Codeforces Round #355 (Div. 2) C. Vanya and Label
- 10040---(总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
- Spring注解@Component、@Repository、@Service、@Controller区别
- 关于虚拟机的两种上网方式(桥接模式和NAT模式)
- Android源码剖析之Framework层升级版(窗口、系统启动)
- Actor事件处理框架介绍
- Java基础