簡體   English   中英

使用 $scope.$watch 並且仍然需要 $scope.$apply?

[英]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-clickng-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM