在 Angular 中使用 $apply() 的正确方法
在 Angular 中,当我们需要手动更新视图(View)时,需要使用 $apply() 方法。官方文档指出,$apply() 是一个函数,在某个作用域中传入一个函数并执行后,会通过 $digest 循环触发数据变化并更新视图。但是,如果 $apply() 不正确使用,可能会导致性能问题、bug 以及难以调试的问题。
在本文中,将介绍在 Angular 中使用 $apply() 的正确方法,探讨如何避免常见的错误和陷阱,并提供一些示例代码。
一、正确的使用方法
(一)$apply() 中传入函数是必须的,而不是选择性的
在官方文档中,$apply() 的描述中提到了传入一个函数。可以这样理解,只有为 $apply() 提供了一个函数作为参数,AngularJS 才会触发应用层面的数据交互,从而使 AngularJS 应用程序的内部模型得到更新。如果不提供函数,则不会触发应用层面的数据交互。
此外,$apply() 中传入函数是为了数据改变推动 $digest 循环的执行,如果不传入函数,则`$digest 调用无意义。
(二)$apply() 只能在 Angular 上下文中使用
在 Angular 中,Angular 只能在自己的上下文中自动检测数据变更和更新视图,而非 Angular 的上下文则不行。因此,如果需要手动更新视图,必须将代码放在 Angular 上下文信任的范围内。
下面是一个例子:
function foo() { var $scope = angular.element($("#divId").scope(); $scope.$apply(function() { /* ... */ }); }
上面代码中用 angular.element 从分层文档对象取得了 $scope。通过将 $scope 传递给 $apply 方法让 AngularJS 被告知其需要更新之前所绑定的属性、指令等。
二、避免常见错误和陷阱
(一)避免 $apply() 嵌套
如果在使用 $apply() 时嵌套了一个 $apply() 调用,很有可能会出现异常。原因是,Angular 会将 $apply() 所产生的数据更改放在 JavaScript 的执行队列尾部,而这些更改通常在浏览器的下一次重绘(repaint)之前才会实际发生。如果嵌套了多个 $apply(),则每一个 $apply() 就会产生一个数据更改,并被放在队列末尾,这样会导致多个循环的数据更改同时被清除或者更新,产生不可预料的结果。
(二)避免过分使用 $apply()
在 Angular 应用程序中,应该尽量避免使用 $apply()。因为,在大多数情况下,Angular 可以自动引发 $digest 循环,并进行数据响应式的更新。
(三)使用 $timeout() 而非 $apply()
$timeout() 是 AngularJS 自带的定时器服务,这个服务的处理函数在调用 $apply() 之前会等待一段时间。这样,代码就能够在 "digest" 识别模式下运行。
三、示例代码
下面是一段使用 $apply() 的示例代码:
mymodule.controller('MainCtrl', ['$scope', function($scope) { $scope.greeting = 'Hello AngularJS'; $("#btn").click(function() { $scope.$apply(function() { $scope.greeting = 'Hello AngularJS!!!'; }); }); }]);
上面代码中,我们在 Angular 范围($scope)中声明了一个变量 Greeting,然后在按钮单击时间中使用 $scope.$apply() 更新变量的值。由于 $apply() 的调用不在 Angular 上下文中被调用。Angular 检测不到正在进行的更改,必须手动触发变更检测流程,并在修改模型属性时引入一些自我保护机制。
结论
$apply() 是 AngularJS 中自动检测更改的一种方式,是维持 AngularJS 数据响应能力的关键。本文介绍了在 AngularJS 中使用 $apply() 的正确方法、避免常见错误和陷阱,并通过实例代码来加以说明。希望可以对读者在使用 AngularJS 开发时有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6721be422e7021665e08a413