ily*_*lyo 1076 angularjs angularjs-scope
我不明白如何使用$scope.$watch和$scope.$apply.官方文档没有帮助.
具体我不明白:
我尝试了本教程,但需要理解$watch并$apply理所当然.
做什么$apply和$watch做什么,以及如何恰当地使用它们?
Łuk*_*man 1727
您需要了解AngularJS如何工作才能理解它.
首先,AngularJS定义了一个所谓的摘要周期的概念.这个循环可以被认为是一个循环,在此过程中AngularJS会检查所有s所监视的所有变量是否有任何变化$scope.因此,如果您已$scope.myVar在控制器中定义并且此变量已标记为正在观察,那么您将隐式告知AngularJS监视myVar循环的每次迭代中的更改.
一个自然的后续问题是:一切都$scope被观看了吗?幸运的是,没有.如果您要观察对您的每个对象的更改$scope,那么很快就需要花费很长时间来评估摘要循环,您很快就会遇到性能问题.这就是为什么AngularJS团队给我们两种方式来声明一些$scope变量被观察(见下文).
有两种方法可以将$scope变量声明为被监视.
<span>{{myVar}}</span>$watch服务手动添加广告1)这是最常见的情况,我相信你以前见过它,但你不知道这在后台创造了一个手表.是的,它有!使用AngularJS指令(例如ng-repeat)也可以创建隐式监视.
广告2)这就是您创建自己手表的方式.$watch服务可以帮助您在附加到的某个值$scope发生更改时运行一些代码.它很少使用,但有时很有帮助.例如,如果您希望每次'myVar'更改时运行一些代码,您可以执行以下操作:
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
Run Code Online (Sandbox Code Playgroud)
您可以将$apply功能视为集成机制.你看,每当你改变一个直接附加到$scope对象的观察变量时,AngularJS就会知道发生了变化.这是因为AngularJS已经知道要监控这些变化.因此,如果它发生在框架管理的代码中,摘要周期将继续.
但是,有时您希望更改AngularJS世界之外的某些值,并看到更改正常传播.考虑一下 - 你有一个$scope.myVar值将在jQuery的$.ajax()处理程序中修改.这将在未来的某个时刻发生.AngularJS不能等待这种情况发生,因为它没有被指示等待jQuery.
为了解决这个问题,$apply已经介绍过了.它可以让您明确地开始消化循环.但是,您应该只使用它来将一些数据迁移到AngularJS(与其他框架集成),但从不将此方法与常规AngularJS代码结合使用,因为AngularJS会抛出错误.
好吧,你应该再次按照教程,既然你知道这一切.摘要周期将确保UI和JavaScript代码保持同步,通过评估附加到所有$scopes的每个观察者,只要没有任何变化.如果摘要循环中没有更多的更改,则认为它已完成.
您可以$scope在Controller中显式地将对象附加到对象,也可以{{expression}}直接在视图中以表单形式声明它们.
我希望这有助于澄清有关这一切的一些基本知识.
进一步阅读:
Mar*_*cok 160
在AngularJS中,我们更新模型,我们的视图/模板"自动"更新DOM(通过内置或自定义指令).
$ apply和$ watch都是Scope方法,与DOM无关.
该概念页(参考"运行")具有$消化循环的一个很好的解释,$应用中,$ evalAsync队列和$观察名单.这是文本附带的图片:

无论代码何时访问范围 - 通常是控制器和指令(它们的链接函数和/或它们的控制器) - 都可以设置一个" watchExpression ",AngularJS将根据该范围进行评估.只要AngularJS进入其$ digest循环(特别是"$ watch list"循环),就会发生此评估.您可以观看单个范围属性,您可以定义一个函数来一起观看两个属性,您可以观察数组的长度等.
当事情发生在"AngularJS内部" - 例如,你输入一个启用了AngularJS双向数据绑定的文本框(即使用ng-model),$ http回调触发等等 - $ apply已被调用,所以我们在上图中的"AngularJS"矩形内.将评估所有watchExpressions(可能不止一次 - 直到没有检测到进一步的更改).
当事情发生在"AngularJS之外" - 例如,你在一个指令中使用了bind()然后该事件触发,导致你的回调被调用,或者一些jQuery注册的回调触发 - 我们仍然在"Native"矩形中.如果回调代码修改任何$ watch正在观看的内容,请调用$ apply进入AngularJS矩形,导致$ digest循环运行,因此AngularJS会注意到更改并发挥其魔力.
Tha*_*var 50
AngularJS扩展了这个事件循环,创建了一个名为AngularJS context.
$表()
每次在UI中绑定某些内容时,都会$watch在$watch列表中插入一个.
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
Run Code Online (Sandbox Code Playgroud)
在这里,我们有$scope.user,第一个输入,我们有$scope.pass,它绑定到第二个输入.这样做我们$watch在$watch列表中添加两个es.
当我们的模板被加载,AKA处于链接阶段时,编译器将查找每个指令并创建$watch所需的所有es.
AngularJS提供$watch,$watchcollection和$watch(true).下面是一个简洁的图表,解释了从观察者那里获得的所有三个深度.
angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
$scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];
$scope.$watch("users", function() {
console.log("**** reference checkers $watch ****")
});
$scope.$watchCollection("users", function() {
console.log("**** Collection checkers $watchCollection ****")
});
$scope.$watch("users", function() {
console.log("**** equality checkers with $watch(true) ****")
}, true);
$timeout(function(){
console.log("Triggers All ")
$scope.users = [];
$scope.$digest();
console.log("Triggers $watchCollection and $watch(true)")
$scope.users.push({ name: 'Thalaivar'});
$scope.$digest();
console.log("Triggers $watch(true)")
$scope.users[0].name = 'Superstar';
$scope.$digest();
});
}
Run Code Online (Sandbox Code Playgroud)
$digest 环当浏览器收到可由AngularJS上下文管理的事件时,$digest将触发循环.该循环由两个较小的循环组成.一个处理$evalAsync队列,另一个处理队列$watch list.在$digest通过的名单将循环$watch,我们有
app.controller('MainCtrl', function() {
$scope.name = "vinoth";
$scope.changeFoo = function() {
$scope.name = "Thalaivar";
}
});
{{ name }}
<button ng-click="changeFoo()">Change the name</button>
Run Code Online (Sandbox Code Playgroud)
这里我们只有一个,$watch因为ng-click不会创建任何手表.
我们按下按钮.
$digest循环运行,并会要求每$表更改.$watch正在观察$ scope.name中的更改报告更改,因此将强制执行另一个$digest循环.$digest循环.这意味着每次我们在输入中写一个字母时,循环都将$watch在此页面中运行检查.如果$apply在事件被触发时调用,它将通过angular-context,但是如果你不调用它,它将在它之外运行.就是这么简单.$apply将在$digest()内部调用循环,它将遍历所有监视以确保使用新更新的值更新DOM.
该$apply()方法将触发整个$scope链上的观察者,而该$digest()方法仅触发当前$scope及其的观察者children.当所有较高级别的$scope对象都不需要知道本地更改时,您可以使用$digest().
use*_*687 18
我发现了非常深入的视频覆盖$watch,$apply,$digest并在消化周期:
以下是在这些视频中使用的几张幻灯片来解释这些概念(以防万一,如果删除上述链接/不工作).
在上图中,"$ scope.c"未被监视,因为它未在任何数据绑定中使用(在标记中).另外两个($scope.a和$scope.b)将被观看.
从上图:根据各自的浏览器事件,AngularJS捕获事件,执行摘要周期(通过所有手表进行更改),执行监视功能并更新DOM.如果不是浏览器事件,则可以使用$apply或手动触发摘要周期$digest.
更多关于$apply和$digest:
Jeb*_*b50 15
刚读完以上所有内容,无聊而困倦(抱歉,但这是真的).非常技术性,深入,细致,干燥.我为什么要写作?因为AngularJS是庞大的,许多相互关联的概念可以让任何人变得疯狂.我经常问自己,我是不是很聪明才能理解它们?没有!这是因为很少有人可以用所有术语来解释用于dummie语言的技术!好的,让我试试:
1)它们都是事件驱动的东西.(我听到了笑声,但请继续阅读)
如果您不知道什么是事件驱动,那么您可以在页面上放置一个按钮,使用"点击"将其连接到某个功能,等待用户点击它以触发您在其中设置的操作功能.或者想一想SQL Server/Oracle的"触发器".
2)$ watch是"点击".
有什么特别的,它需要2个函数作为参数,第一个给出事件的值,第二个考虑值...
3)$ digest是老板谁不知疲倦地检查,bla-bla-bla但是一个好老板.
4)$ apply为您提供了手动操作的方式,例如防故障(如果点击不启动,则强制它运行.)
现在,让我们让它成为视觉.想象一下,这样可以更容易地抓住这个想法:
在一家餐馆,
- WAITERS应该接受客户的订单,这是
$watch(
function(){return orders;},
function(){Kitchen make it;}
);
Run Code Online (Sandbox Code Playgroud)
- 经理跑来跑去确保所有服务员都醒着,以应对客户的任何变化.这是$digest()
- OWNER有能力根据要求驱动每个人,这是$apply()
| 归档时间: |
|
| 查看次数: |
927757 次 |
| 最近记录: |