问题描述
我不明白如何使用 $scope.$watch
和 $scope.$apply
.官方文档没有帮助.
我不明白的具体内容:
- 它们是否连接到 DOM?
- 如何更新模型的 DOM 更改?
- 它们之间的连接点是什么?
我尝试了本教程,但需要理解$watch
和 $apply
是理所当然的.
$apply
和 $watch
有什么作用,我该如何正确使用它们?
您需要了解 AngularJS 的工作原理才能理解它.
摘要循环和 $scope
首先,AngularJS 定义了一个所谓的消化循环的概念.这个循环可以看作是一个循环,在此期间 AngularJS 检查所有 $scope
所监视的所有变量是否有任何更改.因此,如果您在控制器中定义了 $scope.myVar
并且此变量被标记为正在监视,那么您就隐含地告诉 AngularJS 监视 myVar 上的更改
在循环的每次迭代中.
一个自然的后续问题是:是否所有附加到 $scope
的东西都被监视了?幸运的是,没有.如果您要观察 $scope
中每个对象的变化,那么很快,摘要循环将需要很长时间来评估,并且您很快就会遇到性能问题.这就是为什么 AngularJS 团队给了我们两种方法来声明一些 $scope
变量被监视(阅读下文).
$watch 有助于监听 $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('嘿,myVar 变了!');});$scope.buttonClicked = function() {$scope.myVar = 2;//这将触发 $watch 表达式};}
$apply 能够将更改与摘要周期集成
您可以将 $apply
函数视为一种集成机制.您会看到,每次直接更改附加到 $scope
对象的某个 监视变量时,AngularJS 都会知道更改已经发生.这是因为 AngularJS 已经知道要监控这些变化.因此,如果它发生在框架管理的代码中,则摘要循环将继续.
但是,有时您希望更改 AngularJS 世界之外的某些值,并看到更改正常传播.考虑一下 - 您有一个 $scope.myVar
值,它将在 jQuery 的 $.ajax()
处理程序中进行修改.这将在未来的某个时候发生.AngularJS 不能等待这种情况发生,因为它没有被指示等待 jQuery.
为了解决这个问题,引入了 $apply
.它可以让您明确地开始消化循环.但是,您应该仅使用此方法将一些数据迁移到 AngularJS(与其他框架集成),而不要将此方法与常规 AngularJS 代码结合使用,否则 AngularJS 会抛出错误.
所有这些与 DOM 有什么关系?
好吧,既然你知道了这一切,你真的应该再次学习教程.摘要循环将通过评估附加到所有 $scope
的每个观察者,只要没有任何变化,就可以确保 UI 和 JavaScript 代码保持同步.如果摘要循环中不再发生变化,则认为它已完成.
您可以在 Controller 中显式地将对象附加到 $scope
对象,也可以直接在视图中以 {{expression}}
形式声明它们.>
进一步阅读:
I don't understand how to use $scope.$watch
and $scope.$apply
. The official documentation isn't helpful.
What I don't understand specifically:
- Are they connected to the DOM?
- How can I update DOM changes to the model?
- What is the connection point between them?
I tried this tutorial, but it takes the understanding of $watch
and $apply
for granted.
What do $apply
and $watch
do, and how do I use them appropriately?
You need to be aware about how AngularJS works in order to understand it.
Digest cycle and $scope
First and foremost, AngularJS defines a concept of a so-called digest cycle. This cycle can be considered as a loop, during which AngularJS checks if there are any changes to all the variables watched by all the $scope
s. So if you have $scope.myVar
defined in your controller and this variable was marked for being watched, then you are implicitly telling AngularJS to monitor the changes on myVar
in each iteration of the loop.
A natural follow-up question would be: Is everything attached to $scope
being watched? Fortunately, no. If you would watch for changes to every object in your $scope
, then quickly a digest loop would take ages to evaluate and you would quickly run into performance issues. That is why the AngularJS team gave us two ways of declaring some $scope
variable as being watched (read below).
$watch helps to listen for $scope changes
There are two ways of declaring a $scope
variable as being watched.
- By using it in your template via the expression
<span>{{myVar}}</span>
- By adding it manually via the
$watch
service
Ad 1)This is the most common scenario and I'm sure you've seen it before, but you didn't know that this has created a watch in the background. Yes, it had! Using AngularJS directives (such as ng-repeat
) can also create implicit watches.
Ad 2)This is how you create your own watches. $watch
service helps you to run some code when some value attached to the $scope
has changed. It is rarely used, but sometimes is helpful. For instance, if you want to run some code each time 'myVar' changes, you could do the following:
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
};
}
$apply enables to integrate changes with the digest cycle
You can think of the $apply
function as of an integration mechanism. You see, each time you change some watched variable attached to the $scope
object directly, AngularJS will know that the change has happened. This is because AngularJS already knew to monitor those changes. So if it happens in code managed by the framework, the digest cycle will carry on.
However, sometimes you want to change some value outside of the AngularJS world and see the changes propagate normally.Consider this - you have a $scope.myVar
value which will be modified within a jQuery's $.ajax()
handler. This will happen at some point in future. AngularJS can't wait for this to happen, since it hasn't been instructed to wait on jQuery.
To tackle this, $apply
has been introduced. It lets you start the digestion cycle explicitly. However, you should only use this to migrate some data to AngularJS (integration with other frameworks), but never use this method combined with regular AngularJS code, as AngularJS will throw an error then.
How is all of this related to the DOM?
Well, you should really follow the tutorial again, now that you know all this. The digest cycle will make sure that the UI and the JavaScript code stay synchronised, by evaluating every watcher attached to all $scope
s as long as nothing changes. If no more changes happen in the digest loop, then it's considered to be finished.
You can attach objects to the $scope
object either explicitly in the Controller, or by declaring them in {{expression}}
form directly in the view.
Further readings:
这篇关于如何在 AngularJS 中使用 $scope.$watch 和 $scope.$apply?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!