$apply()函數可以從Angular框架的外部讓表達式在Angular上下文內部執行。例如,假設你實現了一個setTimeout()或者使用第三方庫並且想讓事件運行在Angular上下文內部時,就必須使用$apply()。
簡而言之,使用$scope.$apply()時可以從外部進入上下文。如果在事件被觸發時調用$apply(),就會使用Angular事件循環來運行它。如果沒有調用$apply(),就不會在事件循環內執行這個函數,而它會運行在Angular上下文外部
何時使用$apply
通常可以依賴於Angular提供的可用於視圖中的任意指令來調用$apply()。所有ng-[event]
指令(比如ng-click、ng-keypress)都會調用$apply()。
此外還可以依賴於一系列Angular內置的服務來調用$digest()。比如$http服務會在XHR請求完成並觸發更新返回值(promise)之后調用$apply()。
無論何時我們手動處理事件,使用第三方框架(比如jQuery、Facebook API),或者調用setTimeout(),都可以使用$apply()函數讓Angular返回$digest循環。
當我們將jQuery和Angular集成在一起時(這通常被視為一個骯臟的行為),就需要使用$apply(),因為Angular不會察覺到執行在Angular上下文外部的事件。例如,在使用jQuery插件時(比如datepicker),就需要使用$apply()將來自jQuery的值傳遞到Angular應用中
在這里,我們構建了一個簡單的指令(第10章深入探索了如何構建指令),指令中我們在元素上使用了datepicker這個jQuery插件方法。
datepicker插件暴露了一個onSelect事件,這個事件會在用戶選擇日期時觸發。為了在Angular應用內部獲取用戶選擇的日期,我們需要在$apply()函數內運行datepicker的回調函數
app.directive('myDatepicker', function () { return function (scope, ele, attrs, ctrl) { $(function () { // 在元素上調用datepicker方法 ele.datepicker({ dateFormat: 'mm/dd/yy', onSelect: function (date) { scope.$apply(function () { ctrl.$setViewValue(date); }); } }); }); } });
一般不建議在控制器中使用$apply(),因為這樣會導致難以測試,而且如果不得不在控制器中使用$apply()或者$digest(),很可能讓事情變得更加難以理解。