何谓$apply&$angularjs中的摘要函数及其用法
$apply和$digest函数之间的区别是什么 有人能解释一下apply、digest函数的确切用法吗?angularjs中的差异以及我们可以使用这些函数的场景吗何谓$apply&$angularjs中的摘要函数及其用法,angularjs,Angularjs,$apply和$digest函数之间的区别是什么 有人能解释一下apply、digest函数的确切用法吗?angularjs中的差异以及我们可以使用这些函数的场景吗 //digest function $scope.$digest(); //apply function like this $scope.$apply(function(scope) { scope.demo = "angular"; }); (or) //apply function lik
//digest function
$scope.$digest();
//apply function like this
$scope.$apply(function(scope)
{
scope.demo = "angular";
});
(or)
//apply function like this
$scope.$apply(function()
{
$scope.demo = "angular";
});
谁能解释一下apply、digest函数的确切用法和angularjs中的差异,以及我们可以使用这些函数的场景$digest()
函数迭代$scope对象及其子$scope对象(如果有)中的所有监视。当$scope.$digest()
迭代手表时,它会为每个手表调用value函数。如果value函数返回的值与上次调用时返回的值不同,则调用该手表的侦听器函数$digest()
- 只要
认为有必要,就会调用AngularJS
函数。例如,在执行按钮单击处理程序之后,或者在AJAX调用返回之后(在执行了done()/fail()回调函数之后)$digest()
- 您可能会遇到一些特殊情况,AngularJS不为您调用$digest()函数。您通常会通过注意到数据绑定没有更新显示的值来检测到这一点。在这种情况下,调用$scope.$digest()应该可以工作。或者,您也可以使用$scope.$apply(),我将在下一节中对此进行解释
$apply()
函数将函数作为执行的参数,然后在内部调用$scope.$apply()
。这使您更容易确保检查所有手表,从而刷新所有数据绑定。下面是一个$scope.$digest()
示例:$apply()
$scope.$apply(函数(){ $scope.data.myVar=“另一个值”; });代码>
- 作为参数传递给
函数的函数将更改$apply()
的值。当函数退出时,$scope.data.myVar
将调用“$scope.$digest()函数,以便检查所有监视值的变化AngularJS
:对$scope.$digest()
和子项运行摘要循环$scope
:计算$scope.$apply(expr)
并在expr
上运行摘要循环$rootScope
$scope.$digest()
(除非您确实知道自己在做什么),因为它不会将更改传播到$scope
的子树之外
非常非常简短(因为有大量资源(帖子、教程等)解释了深度上的差异):
在
$scope
上启动摘要循环,即评估$scope
的观察者及其子对象的观察表达式,并在必要时执行观察操作。根据需要多次重复此循环,直到所有值稳定(取决于参数)
解析
expr
并在$scope
的上下文中对其求值。然后它调用$rootScope.$digest()
,它基本上评估应用程序中的所有观察者(因为每个作用域都是$rootScope
的子对象)
解析expr
(使用$parse
)函数中的结果(或多或少),当使用上下文作为参数(例如作用域)调用函数时,返回在该上下文中计算expr
的结果。Angular将调用此函数作为上下文传入$scope
。
如果expr
已经是一个函数,则不需要实际解析(同样,这可能有点过于简化,但适用于大多数情况)。
另外需要注意的是,在$apply()
中执行代码会捕获错误,然后通过$exceptionHandler
(这是一个额外的好处)
一些例子:
// Let there be Scopes...
var scope1 = $rootScope.$new();
var scope2 = $rootScope.$new();
var scope2_1 = scope2.$new();
// Let there be watchers...
$rootScope.$watch(/* RootWatcher */);
scope1.$watch(/* Scope1Watcher */);
scope2.$watch(/* Scope2Watcher */);
scope2_1.$watch(/* Scope2_1Watcher */);
// Let there be `$digest`s...
$rootScope.$digest(); // Evaluates ALL watchers
scope1.$digest(); // Evaluates ONLY Scope1Watcher
scope2.$digest(); // Evaluates BOTH Scope2Watcher, Scope2_1Watcher
scope2_1.$digest(); // Evaluates ONLY Scope2_1Watcher
// Let there be `$apply`s...
$rootScope.$apply(); // Runs $rootScope.$digest()
scope1.$apply(); // Still runs $rootScope.$digest()
scope1.$apply('test = 42'); // Boils down to: scope1.test = 42
// ...and is equivalent to:
scope1.$apply(function (scope) { scope.test = 42; });
// ...which in turn is equivalent to:
scope1.$apply(function (ignored) { scope1.test = 42; });
// So, I could have a reusable function:
var assign42 = function (scope) { scope.test = 42; };
scope1.$apply(assign42); // Boils down to: scope1.test = 42;
scope2.$apply(assign42); // Boils down to: scope2.test = 42;
scope2_1.$apply(assign42); // Boils down to: scope2_1.test = 42;
$apply()
另一个值得注意的地方是捕捉错误并将其传递给Angular(这是一件好事)。例如:
不用说,Angular(如果使用得当)将为您处理摘要生命周期,因此您不必手动调用
$digest()
/$apply()
。
例外情况是绑定到DOM元素的事件处理程序和在Angular上下文之外运行的第三方代码中的回调。
这在文档中也有很好的解释:,检查任何绑定值是否已更改的步骤实际上有一个方法,
$scope.$digest()
。这就是神奇发生的地方,但我们几乎从不直接调用它,而是使用$scope.$apply()
为您调用$scope.$digest()
$scope.$apply()
获取函数或角度表达式字符串并执行它,然后调用$scope.$digest()
以更新任何绑定或观察程序
那么,什么时候需要调用$apply()
实际上很少。AngularJS实际上在$apply调用中调用了几乎所有的代码。像ng click
、控制器初始化、$http
回调之类的事件都包装在$scope.$apply()
中。所以你不需要自己称呼它,事实上你不能。在$apply内调用$apply
将抛出错误
如果要在新一轮中运行代码,您确实需要使用它。而且只有在这个转折点不是从AngularJS库中的方法创建的情况下。在新回合中,您应该将代码包装在$scope.$apply()
中。这里有一个例子。我们正在使用setTimeout,它将在延迟后的新回合中执行一个函数。由于Angular不知道该新转向,因此不会反映更新
function Ctrl($scope) {
$scope.message = "Waiting 2000ms for update";
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
}
回答不错,但不管是善意还是错误:)
$scope.$apply()
不一定需要函数(例如,它可以
// Let there be Scopes...
var scope1 = $rootScope.$new();
var scope2 = $rootScope.$new();
var scope2_1 = scope2.$new();
// Let there be watchers...
$rootScope.$watch(/* RootWatcher */);
scope1.$watch(/* Scope1Watcher */);
scope2.$watch(/* Scope2Watcher */);
scope2_1.$watch(/* Scope2_1Watcher */);
// Let there be `$digest`s...
$rootScope.$digest(); // Evaluates ALL watchers
scope1.$digest(); // Evaluates ONLY Scope1Watcher
scope2.$digest(); // Evaluates BOTH Scope2Watcher, Scope2_1Watcher
scope2_1.$digest(); // Evaluates ONLY Scope2_1Watcher
// Let there be `$apply`s...
$rootScope.$apply(); // Runs $rootScope.$digest()
scope1.$apply(); // Still runs $rootScope.$digest()
scope1.$apply('test = 42'); // Boils down to: scope1.test = 42
// ...and is equivalent to:
scope1.$apply(function (scope) { scope.test = 42; });
// ...which in turn is equivalent to:
scope1.$apply(function (ignored) { scope1.test = 42; });
// So, I could have a reusable function:
var assign42 = function (scope) { scope.test = 42; };
scope1.$apply(assign42); // Boils down to: scope1.test = 42;
scope2.$apply(assign42); // Boils down to: scope2.test = 42;
scope2_1.$apply(assign42); // Boils down to: scope2_1.test = 42;
// BAD - Avoid doing this:
somePossiblyErrorThrowingFunc();
scope.$apply();
// GOOD - Do this instead:
scope.$apply(somePossiblyErrorThrowingFunc);
function Ctrl($scope) {
$scope.message = "Waiting 2000ms for update";
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
}