在指令中使用 $scope.$watch 处理未定义变量的替代方法

Alternatives to using $scope.$watch in directive to handle undefined variable

本文关键字:变量 未定义 方法 处理 watch 指令 scope      更新时间:2023-09-26

我正在使用angularjs开发一个应用程序,我也在使用指令,因为某些UI在多个页面上重复使用。当我有一个依赖于承诺值的指令时,我必须使用 $scope.$watch 和一个 if 条件来检查未定义,因为指令在承诺完成之前编译。下面是一个示例:

myAppModule.directive('topicDropdown', function () {
        return {
            templateUrl: 'Scripts/app/shared/dropdown/tmplTopic.html',
            restrict: 'AE',
            scope: {
                subjectId: '=',
                setDefault: '=',
                topicId: '='
            },
            controller: [
               '$scope', 'service', function ($scope, service) {
                   $scope.$watch('subjectId', function () {
                       if ($scope.subjectId != undefined)
                           $scope.getTopics();
                   });
                   $scope.getTopics = function () {
                       service.get("section/topics/" + $scope.subjectId).then(function (data) {
                           $scope.listOfTopics = data;
                           if ($scope.setDefault) {
                               $scope.subjectId = $scope.listOfTopics[0].UniqueId;
                           }
                       });
                   }
               }
            ]
        }
    });

subjectId 最终将来自一个承诺,但没有$watch我将得到一个未定义的错误,因为它将在没有 ID 的情况下触发 getTopics。

scope: {
                subjectId: '=',
                setDefault: '=',
                topicId: '='
            },

目前,这段代码可以工作,但我必须在每次 subjectId 更改时调用摘要循环,这将遍历范围正在监视的所有内容。我只关心此时主题ID何时更改。

我还看到了一些将ng-if用于模板html的建议。像这样:

<div ng-if="subjectId != undefined">
    <topic-dropdown subject-id="subjectId"></topic-dropdown>
</div>

有了这个,我不必使用 $scope.$watch 但是我不确定这是否是最好的方法。

有没有人有解决这个问题的好方法?是否有任何我不知道的指令属性?

缺口

为 subjectId 传递一个承诺,并getTopics等待它解析。它看起来像这样:

$scope.getTopics = function () {
    $scope.subjectIdPromise.then(function (subjectId) {
        $scope.subjectIdPromise = service.get("section/topics/" + subjectId)
        .then(function (data) {
            $scope.listOfTopics = data;
            if ($scope.setDefault) {
                return data[0].UniqueId;
            } else { return subjectId; }
        });
    });
};

这样做的方式是对subjectId的所有访问都是在then成功函数中完成的。如果您想更改subjectId请用新承诺替换承诺。

尝试使用承诺模式,

myAppModule.directive('topicDropdown', function () {
    return {
        templateUrl: 'Scripts/app/shared/dropdown/tmplTopic.html',
        restrict: 'AE',
        scope: {
            subjectId: '=',
            setDefault: '=',
            topicId: '='
        },
        controller: [
           '$scope', 'service', function ($scope, service) {
               $q.when($scope.subjectId).then(
            service.get("section/topics/" + $scope.subjectId).then(function (data) {
                   $scope.listOfTopics = data;
                   if ($scope.setDefault) {
                       $scope.subjectId = $scope.listOfTopics[0].UniqueId;
                   }
               });
            )
        ]
    }
});
OR
myAppModule.directive('topicDropdown', function ($q) {
    return {
        templateUrl: 'Scripts/app/shared/dropdown/tmplTopic.html',
        restrict: 'AE',
        scope: {
            subjectId: '=',
            setDefault: '=',
            topicId: '='
        },
        link: function(scope, element, attrs){
         $q.when(subjectId).then(
            service.get("section/topics/" + scope.subjectId).then(function (data) {
                   scope.listOfTopics = data;
                   if (scope.setDefault) {
                       scope.subjectId = scope.listOfTopics[0].UniqueId;
                   }
               });
            )
        }
    }
});

但我认为您将以一种或另一种方式使用$watch。使用$watch不会伤害任何东西,它的角度方式可以保持事物的连接。