首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AngularJS指令回调函数计时问题

AngularJS指令回调函数计时问题
EN

Stack Overflow用户
提问于 2017-01-28 06:30:43
回答 1查看 245关注 0票数 2

我偶然发现了一个角度问题,我既不理解也不知道如何解决这个问题。

我希望在控制器中有一个回调函数,一旦做了某件事,指令就会调用它。该指令首先修改一些作用域变量并运行回调。然后,回调函数继续对相同的作用域变量执行某些操作。这可能看起来令人困惑,因为我需要这样做,但考虑到该指令是通用的,并处理许多不同的情况,而回调是一个非常特定的函数。需要注意的是,我不能将这个变量作为参数传递,因为其他代码也需要使用这个作用域变量。

现在来看看问题。在回调被执行之前,我把一切都准备好了。似乎在回调中,变量还没有改变。但是,如果设置了超时(在我的示例中为一秒),则该变量将被识别为已更改。为什么它会有这样的行为?即使在调用回调之前的指令中,它也会显示变量实际上已更改。我已经创建了一个Codepen来演示这个问题。它只是将按钮标签从'A‘切换到'B’。不过你会注意到,在控制台日志中,当变量在回调中打印时,它是'old‘值,直到我等待。

任何信息都会很棒的,谢谢!

注意:我想到的一个想法是将作用域变量的副本保存为指令中的局部变量,并将该局部变量作为参数发送到回调,因为回调是我目前唯一关心的函数,它可以立即知道变量的更改并对其执行操作。

Codepen:http://codepen.io/anon/pen/KayaRW

HTML:

代码语言:javascript
复制
<div ng-app="myApp" ng-controller="myCtrl">
   <div ng-test="" button-label="myLabel" callback="cbFunc()">
   </div>
</div>

JS:

代码语言:javascript
复制
angular
   .module('myApp', [])
   .controller('myCtrl', function($scope) {

      $scope.myLabel = "A";

      $scope.cbFunc = function() {
          console.log("myLabel in callback: " + $scope.myLabel);
          setTimeout(function() {
            console.log("myLabel in callback, after 1 sec: " + $scope.myLabel);
            console.log("");
         }, 1000);
      }

   }).directive('ngTest', function() {
      return {
         scope: {
            buttonLabel: '=',
            callback: '&'
         },
         template: function(element, attrs) {
            element.html("<button class=\"btn\" ng-click=\"changeLabel()\">Button Label: {{buttonLabel}}</button>");
         },
         link: function($scope, $element, $attrs) {
            $scope.changeLabel = function() {
               if ($scope.buttonLabel == "A") {
                  $scope.buttonLabel = "B";
               } else {
                  $scope.buttonLabel = "A";
               }
               console.log("myLabel before callback: "+ $scope.buttonLabel);
               $scope.callback();
            }
         }
      }
   });
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-28 09:39:05

你有几个选择。我相信你的问题发生是因为指令创建了一个孤立的作用域。为了提高可读性,我还将指令更改为一个元素:

1)不要使用回调,您的$scope.myLabel已经双向绑定了。

2)您可以将超时设置为0,但它似乎仍然有效。我使用了$timout服务:

代码语言:javascript
复制
<div ng-app="myApp" ng-controller="myCtrl">
  <ng-test button-label="myLabel" callback="cbFunc()"> </ng-test>
  <p>
 Here is the updated label in the timeout::::: {{updatedLabel}}
  </p>
</div>
angular
  .module('myApp', [])
  .controller('myCtrl', function($scope, $timeout) {
  $scope.myLabel = "A"; //inital value
  $scope.cbFunc = function() {
    $timeout(function() {
    //$scope.myLabel is updated, $timeout is like an $apply but better
    }, 0);
  }
}).directive('ngTest', function() {
  return {
   restrict: 'E',
    scope: {
      buttonLabel: '=',
      callback: '&'
    },
    template: function(element, attrs) {
      element.html("<button class=\"btn\" ng-click=\"changeLabel()\">Button Label: {{buttonLabel}}</button>");
    },
    link: function($scope, $element, $attrs) {
      $scope.changeLabel = function() {
        if ($scope.buttonLabel == "A") {
          $scope.buttonLabel = "B";
        } else {
          $scope.buttonLabel = "A";
        }

        $scope.callback();
      }
    }
  }
});

3)你的回调可以接受参数,指令会把它传回,你说过这并不是一个真正的选择。

代码语言:javascript
复制
<div ng-app="myApp" ng-controller="myCtrl">
  <ng-test button-label="myLabel" callback="cbFunc(data)"> </ng-test>
  <p>
 Here is the updated label in the timeout::::: {{updatedLabel}}
  </p>
</div>

angular
  .module('myApp', [])
  .controller('myCtrl', function($scope,$timeout) {
 $scope.myLabel = 'A';

 $scope.cbFunc = function(data){
   $scope.updatedLabel = data;
 }

}).directive('ngTest', function() {
  return {
    restrict: 'E',
    scope: {
      buttonLabel: '=',
      callback: '&'
    },
    template: function(element, attrs) {
      element.html("<button class=\"btn\" ng-click=\"changeLabel()\">Button Label: {{buttonLabel}}</button>");
    },
    link: function($scope, $element, $attrs) {
      $scope.changeLabel = function() {
        if ($scope.buttonLabel == "A") {
          $scope.buttonLabel = "B";
        } else {
          $scope.buttonLabel = "A";
        }

        $scope.callback({data: $scope.buttonLabel});
      }
    }
  }
});

4) $emit对象在每次更新时备份,控制器可以监听它。在指令中,不是调用回调,而是调用

代码语言:javascript
复制
$scope.$emit('sudoCallback', $scope.buttonLabel);

在您的控制器中,而不是在回调函数中

代码语言:javascript
复制
 $scope.$on('sudoCallback', function(event, data) {$scope.updatedLabel = data });

我不喜欢这个选项,因为作用域层次结构可能会导致问题

5)在$scope.myLabel的控制器中使用$watch,彻底去掉回调。

代码语言:javascript
复制
  $scope.$watch('myLabel', function(newVal){
    $scope.updatedLabel = newVal;
  });

我不喜欢添加一堆手表,但它可以工作。

github上还有一个相当酷的库,它充当消息中心,因此您不需要关心作用域层次结构,只需订阅和发布即可。GitHub Angular Message Bus

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41904088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档