【问题标题】:Controller variable not updating before Custom-Directive operation控制器变量在自定义指令操作之前未更新
【发布时间】:2019-12-01 22:11:25
【问题描述】:

我是 angularJS 的新手(我知道学习 angularJS 已经晚了,但现在总比不学好......对吧?)并且一直在玩一些简单的任务。 最近,我试图深入研究数据如何在控制器、自定义指令和自定义指令控制器之间交换、更新。 在一个简单的实现中,我尝试在自定义指令控制器中创建一个点击计数器,它将从主控制器启动计数变量,将对自定义指令中的该变量进行计数操作。在自定义指令中有两个计数操作。第一个操作是 count +1,第二个操作是对另一个变量 +2。然后通过单击“CLICK”按钮调用主控制器中的一个函数,然后将两个计数相乘并产生结果。

在这里,我面临的问题是:

单次增量:1 双倍增量:2 结果:0(应该是:2)

单次增量:2 双倍增量:4 结果:4(应该是:8)

单次增量:3 双倍增量:6 结果:12(应该是:18)

单次增量:4 双倍增量:8 结果:24(应该是:32),反之亦然....

意味着自定义指令控制器中的“$scope.count”在“onClick()”事件中递增,但主控制器的“$scope.count”在“onClick()”事件中不递增,而是保留之前的值,尽管双向绑定在起作用。

如何解决这个问题?

var myApp = angular.module('myModule', []);

myApp.controller('myController', function($scope) {
  $scope.count = 0;
  $scope.result = 0;

  $scope.increase = function(dircount) {
    $scope.result = dircount * $scope.count;
  };
});

myApp.directive('helloWorld', function() {
  return {
    restrict: 'AEC',
    replace: true,
    template: '<div><div>Increment from Directive: SINGLE INCREMENT {{singleInc}} times</div>' +
      '<div><button  ng-click="click()">CLICK</button></div></div>',
    scope: {
      counT: '=',
      onClick: '&'
    },
    controller: function($scope, $timeout) {
      $scope.singleInc = 0;
      $scope.click = function() {
        $scope.singleInc++;
        $scope.counT += 2;
        $scope.onClick({
          item: $scope.singleInc
        });

      };
    }
  };
});
<html ng-app="myModule"> 

<head><title> Click-Counter Multiplier</title>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js" </script>
    <script src = "https://code.jquery.com/jquery-3.2.1.slim.min.js"
    integrity = "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
    crossorigin = "anonymous" >
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
  <script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
</head>

<body>
  <div ng-controller="myController">
    <p>Result: {{result}}</p>
    <p>From Controller: DOUBLE INCREMENT {{count}}</p>
    <hello-world coun-t="count" on-click="increase(item)"></hello-world>
    </br>
  </div>
</body>

</html>

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    出现问题是因为双向 (=) 绑定涉及指令的隔离范围和父控制器范围之间的摘要循环延迟。

    避免延迟的一种方法是使用表达式 (&amp;) 绑定进行更改:

    myApp.directive('helloWorld', function() {
      return {
        restrict: 'AEC',
        replace: true,
        template: `
            <div>
              <div>Increment from Directive: SINGLE INCREMENT {{singleInc}} times
              </div>
              <div>
                <button ng-click="click()">CLICK</button>
              </div>
            </div>
        `,
        scope: {
          counT: '<',
          counTChange: '&',
          onClick: '&'
        },
        controller: function($scope, $timeout) {
          $scope.singleInc = 0;
          $scope.click = function() {
            $scope.singleInc++;
            $scope.counT += 2;
            $scope.counTChange({$event: $scope.counT});
            $scope.onClick({
              item: $scope.singleInc
            });    
          };
        }
      };
    });
    

    用法:

    <hello-world coun-t="count" cont-t-change="count=$event" on-click="increase(item)">
    </hello-world>
    

    它使模板更复杂,但它避免了导致问题的摘要周期延迟。

    这是 Angular 2+ 使用香蕉盒 ([(coun-t)]=count) 语法的方式。

    【讨论】:

    • 感谢@georgeawg 的回复。当控制器和指令位于单个文件中时,您的解决方案就像一个魅力。但是,当它们位于单独的文件中时,控制器的变量不会由于您的动态“$timeout(function () {$scope.onClick({ item: $scope.singleInc });}, 0)Done!
    猜你喜欢
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    相关资源
    最近更新 更多