javascript - Angular Controller 调用指令上的函数是 'bad practice' 吗?

标签 javascript angularjs model-view-controller controller angularjs-directive

我有一个 Angular 指令,它实现了本质上是自定义组合框的功能。单击输入控件会导致另一个 div 出现在其下方,并显示模型对象中包含的 div 的列表。您可以在输入控件中键入文本,它会过滤其下方的 div 列表。

我有一些单独的按钮对象(不是指令的一部分,但在同一范围内),它们调用 $scope.clearFilter() 或 $scope.unselectAll() 等方法,而这些方法又调用directiveScope.clearFilter () 或directiveScope.unselectAl()。 DirectiveScope 是组合框指令和主 Controller 之间的共享对象。它使 Controller 能够直接调用指令上的方法。

我整理了一个小Plunker展示我目前的做法。这是一个“本着精神”类型的示例,而不是我的确切代码(许可证问题)。

// HTML
<my-directive sharedobj="myDirective1"></my-directive>
<input type="button" ng-click="clearFilterText1()" value="Clear"/><br/><br/>

// JS
var app = angular.module( 'Test', [] );

app.controller( 'MyController', [ '$scope', function( $scope ) {
  $scope.myDirective1 = {};
  $scope.myDirective2 = {};

  $scope.clearFilterText1 = function() {
    console.log("Calling directive 1");
    $scope.myDirective1.clearFilterText();
  }

  $scope.clearFilterText2 = function() {
    console.log("Calling directive 2");

    // QUESTION: If calling this directive method is bad practice, what is 
    //           equivalent good practice?
    $scope.myDirective2.clearFilterText();
  }
}]);

app.directive( 'myDirective', function() {
  return {
    template: "<div><input type='text' ng-model='filterText'/></div>",
    scope: {
      sharedobj: "="
    },
    restrict: 'E',
    replace: true,
    link: function( scope, elem, attrs ) {

      // This is the text that the directive will show, and it is conceptually private
      // to the directive, so I'd rather not put this into the controller scope.
      scope.filterText = "filter this!";

      // This method is on the "sharedobj" that is linked into the controller.
      // The controller is able to call this method directly, which updates
      // the view state.  This simply updates "view state".
      scope.sharedobj.clearFilterText = function() {
        console.log("Setting filter text!");
        scope.filterText = "";
      }

    }
  };
});

有人告诉我,让 Angular Controller 直接调用指令上的方法并不是好的设计,但根据Wikipedia's page on MVC :

A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).

如果“发送命令”与“调用函数”同义,并且如果您将指令视为“ View ”,那么这听起来正是我正在做的事情,因为指令本质上是 HTML 的扩展。

我看过 StackOverflow 帖子,如 this one这也表明这是一个坏主意(没有理由证明该立场),但建议的替代方案是实现一个单独的服务来处理这种状态,这似乎是一个不必要的复杂解决方案,特别是因为我有这些组合框指令的多个实例。您最终会得到一个甚至不知道自己的 View 状态的指令,这看起来非常错误。

我不明白为什么调用 SomeService.clearFilter()(然后设置指令必须 $watch() 执行的一些“状态”)比仅仅调用 someDirective.clearFilter() 并避免所有开销更好。 Controller 仍然需要了解如何清除过滤器。它只需注入(inject) SomeService 而不是连接到指令。

所以,Angular/MVC 专家,请告诉我为什么这是错误的(或者为什么可以)! :-)

谢谢。

最佳答案

看到这一点的简单方法是指令被认为是独立的或添加行为。当您通过 Controller 调用它们的函数时,您实际上是在使指令依赖于该 Controller 的存在,而不是像它可以/应该那样可重用。

还有其他方法可以实现相同的结果,而无需将 viewController 耦合到指令,但这取决于每种具体情况,因此如果没有更多信息,我无法帮助您:(

干杯

关于javascript - Angular Controller 调用指令上的函数是 'bad practice' 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25560014/

相关文章:

javascript - Mapbox JS SDK 地理编码客户端未定义

javascript - 对 Angular 和 rails 一起布线感到困惑

java将日期插入数据库

c# - 在 .Net Core 2.0 中使用 Session

javascript - 并行运行多个异步函数的安全方法?

javascript - 客户关系管理 2013 : Global JavaScript

AngularJS passportJS 用户在页面重新加载后注销

javascript - ng-model 在 ng-if 和 ng-repeat、AngularJs 中不起作用?

c++ - 如何用QAbstractItemDelegate的画图在QListVIew的单元格中心设置QRect?

javascript - 为什么我需要 `module.exports` 开 Jest ?我怎样才能避免它?