32

我想编写一个具有隔离范围的指令,但也想让该范围可用于父范围的控制器。我找到了这个解决方案:

<div ng-controller="Main">
  <popupbutton directive-scope="popup"></popupbutton>
</div>

app.directive('popupbutton', [function() {
  return {
    restrict:   "E",
    scope:      {    
      directiveScope: "="
    },
    link:       function(sc, el, attrs) {
      sc.directiveScope = sc;
      sc.testvalue = 'foo';
    }
  };  
}]);

app.controller('Main', function($scope) {
  alert($scope.popup.testvalue);  // Where did the property 'popup' come from?!?
});

请参阅Plunker

我觉得这有点难看,因为它涉及在 HTML 中编写一个属性,并且在控制器的代码中你无法分辨范围属性的来源。有一个更好的方法吗?

编辑:

此外,似乎 $scope.popup 在控制器“Main”运行时甚至都不可用。指令的链接功能还没有执行?

4

1 回答 1

46

为了保持适当的关注点分离,您不应该混合范围。更不用说它会很难同步。总结一下:你的指令不应该知道任何关于父作用域(或其控制器)的信息,你的控制器不应该知道任何关于指令内部的信息。它们是不同层中的独立组件。

在控制器和指令之间进行通信的正确方法是通过指令属性。例如,在弹出窗口的情况下,这可以通过一个简单的布尔值来完成。

控制器和指令:

app.directive('popupbutton', [function() {
  return {
    restrict: "E",
    scope: { isOpen: "=" },
    template: '<a ng-click="isOpen = !isOpen">Toggle</a><div>Open? {{isOpen}}'
  };
}]);

app.controller('MainCtrl', function($scope) {
  $scope.isOpen = false;
});

和标记:

<popupbutton is-open="isOpen"></popupbutton>

这种方法不需要逻辑,开箱即用,并保持关注点的清晰分离。这是一个更新的 plunker:http ://plnkr.co/edit/otIaGCLmiNdGcYEgi60f?p=preview

于 2013-01-27T06:56:23.047 回答