[英]Using $scope.$watch and still need $scope.$apply?
我已經實現了一個 filedrop 指令,將文件放入 ngModel 中。
<filedrop data-ng-model="file"></filedrop>
我在控制器中使用以下代碼:
$scope.$watch('file', function(newVal, oldVal) {
if (newVal) {
var reader = new FileReader();
reader.onload = function(event) {
$scope.parseFile(newVal);
};
reader.readAsDataURL(newVal);
}
}, false);
在 $scope.parseFile 我實際上解析了 XLSX:
$scope.parseFile = function(file) {
xlsxParser.parse(file).then(function(data) {
console.log("Number of columns", data.datasheet[1].length);
console.log("Number of rows", data.datasheet.length);
$scope.validationErrors = [];
$scope.brand = {
items: []
};
$scope.dataItems = [];
$scope.datasheetValidate(data.datasheet, $scope.brand);
$scope.datasheetData(data.datasheet, $scope.dataItems);
if ($scope.validationErrors.length == 0) $scope.validationErrors.push("Nice work, no validation errors");
//$scope.$apply(function(){});
}, function(err) {
console.log('error', err);
});
}
如您所見,我注釋掉了//$scope.$apply(function(){});
在身體里....
但是,我需要它以便使用范圍更改更新我的網頁(例如顯示validationErrors
)
我怎么需要$scope.$apply
?
使用 $scope.$watch 並不重要。 當您從 Angular 領域之外的reader.onload
回調內部調用$scope.parseFile
,這reader.onload
。
$scope.$apply
應該在回調內部使用:
reader.onload = function(event) {
$scope.$apply(function(){
$scope.parseFile(newVal);
});
};
$scope.$watch
和$scope.$apply
是互補的。
$scope.$watch
在作用域上注冊一個新的觀察者。 只要有一個摘要循環,watch 函數就會運行。
$scope.$apply
觸發一個摘要循環——也就是說,如果沒有任何東西調用過$scope.$apply
,則根本不會運行觀察者。
對於處理用戶輸入( ng-click
、 ng-keydown
等)和內置服務( $http
、 $location
、 $timeout
等)的內置指令,Angular 會為您調用$scope.$watch
. 但是,每當您處理這些內置指令或服務之外的異步代碼時,您都必須告訴 Angular 它應該通過自己調用$apply
來啟動一個新的摘要循環。
正如 Stewie 所提到的,你應該盡量讓你的$apply
調用盡可能接近異步操作; 在這種情況下,這意味着在onload
回調的最頂層使用它。
如果 xlsxParser.parse(file).then 不是角度承諾回調方法,我會看到這種情況發生的唯一原因。
正如@Sander 所證實的那樣,這確實不是一個有角度的承諾,所以這里的選擇是繼續使用現有的 $scope.$apply 調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.