理解$watch ,$apply 和 $digest --- 理解数据绑定过程

本文深入探讨AngularJS的工作机制,解析$watch与$digest循环的作用,以及AngularJS如何响应用户交互并更新DOM。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们的浏览器一直在等待事件,比如用户交互。假如你点击一个按钮或者在输入框里输入东西,事件的回调函数就会在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);







资源下载链接为: https://pan.quark.cn/s/d37d4dbee12c A:计算机视觉,作为人工智能领域的关键分支,致力于赋予计算机系统 “看懂” 世界的能力,从图像、视频等视觉数据中提取有用信息并据此决策。 其发展历程颇为漫长。早期图像处理技术为其奠基,后续逐步探索三维信息提取,与人工智能结合,又经历数学理论深化、机器学习兴起,直至当下深度学习引领浪潮。如今,图像生成合成技术不断发展,让计算机视觉更深入人们的日常生活。 计算机视觉综合了图像处理、机器学习、模式识别深度学习等技术。深度学习兴起后,卷积神经网络成为核心工具,能自动提炼复杂图像特征。它的工作流程,首先是图像获取,用相机等设备捕获视觉信息并数字化;接着进行预处理,通过滤波、去噪等操作提升图像质量;然后进入关键的特征提取描述环节,提炼图像关键信息;之后利用这些信息训练模型,学习视觉模式规律;最终用于模式识别、分类、对象检测等实际应用。 在实际应用中,计算机视觉用途极为广泛。在安防领域,能进行人脸识别、目标跟踪,保障公共安全;在自动驾驶领域,帮助车辆识别道路、行人、交通标志,实现安全行驶;在医疗领域,辅助医生分析医学影像,进行疾病诊断;在工业领域,用于产品质量检测、机器人操作引导等。 不过,计算机视觉发展也面临挑战。比如图像生成技术带来深度伪造风险,虚假图像视频可能误导大众、扰乱秩序。为此,各界积极研究检测技术,以应对这一问题。随着技术持续进步,计算机视觉有望在更多领域发挥更大作用,进一步改变人们的生活工作方式 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值