AngularJS - 指令更改服务中的数据时视图未更新

AngularJS - view not updated when directive changes data in service

我正在使用指令与服务交互,但在显示最新数据的视图中遇到了一些问题。

我设置了以下示例。您可以看到,当控制器与服务交互时,视图将更新为最新数据。如果单击指令 link,您可以在控制台中看到数据已更改,但视图未使用该数据更新。

http://jsfiddle.net/kisonay/pv8towqc/

我错过了什么?

JavaScript:

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

app.factory('Service', function() {
  var Service = {};
  Service.data = {};
  Service.data.active = false;
  Service.data.one = {};
  Service.data.many = [];
  Service.changeActive = function(state) {
    state = state || false;
    Service.data.active = state;
  };
  Service.setOne = function(one) {
    Service.data.one = one;
  };
  Service.setMany = function(many) {
    Service.data.many = many;
  };
  return Service;
});

app.directive('launcher', function(Service) {
  return {
    restrict: "A",
    link: function(scope, elem, attrs) {
      elem.bind('click', function(event) {
        if (Service.data.active) {
          Service.changeActive(false);
        } else {
          Service.changeActive(true);
        }
        console.log(Service.data); // shows data changed
      });
    }
  };
});

function Ctrl1($scope, Service) {
  $scope.ServiceData = Service.data;
}

function Ctrl2($scope, Service) {
  $scope.active = function() {
    Service.changeActive(true);
  };
  $scope.inactive = function() {
    Service.changeActive(false);
  };
}

HTML

<div ng-controller="Ctrl1">
  {{ServiceData}}
</div>

<hr />

<div ng-controller="Ctrl2">
  Directive: <a href="#" launcher>Change</a>
  <hr /> Controller:

  <button ng-click="active()">
    Active
    </button>
  <button ng-click="inactive()">
    Inactive
    </button>
</div>

您的事件侦听器已执行,但 Angular 对此一无所知,因此它不知道必须检测更改。

在点击监听器的evn处添加scope.$apply();,它会按预期工作。

app.directive('launcher', function(Service) {
  return {
    restrict: "A",
    link: function(scope, elem, attrs) {
      elem.bind('click', function(event) {
        scope.$apply(function() {
          if (Service.data.active) {
            Service.changeActive(false);
          } else {
            Service.changeActive(true);
          }
        });
      });
    }
  };
});