指令应该与Angular JS中的控制器通信吗?

时间:2013-04-05 12:59:40

标签: angularjs

我一直在观看John Linquist的视频,并在一个视频中以此为例:

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

app.controller("AppCtrl", function ($scope) {
   $scope.loadMoreTweets = function () {
      alert("Loading tweets!");
   }
}

app.directive("enter", function() {
   return function (scope, element, attrs) {
      element.bind("mouseenter", function () {
         scope.LoadMoreTweets();
      })
   }
}

我想知道的一件事是,本示例中的指令应该与控制器对话,还是创建服务然后让指令与服务进行通信是一种更好的编程习惯?我想我仍然不确定指令以这种方式与控制器通信是否是常见做法。

U tube video

3 个答案:

答案 0 :(得分:6)

我将如何做到

<span enter="loadMoreTweets()">Something</span>

JS

app.controller('AppController', function ($scope) {
   $scope.loadMoreTweets = function () {
      console.log("Loading tweets!");
   }  
})



app.directive("enter", function() {
   return {
     link: function (scope, element, attrs) {
       element.bind("mouseenter", function () {
          scope.$apply(attrs.enter)
       })
     }
   }
});

演示:Plunker

实现相同的另一种方式

app.directive("enter", function() {
   return {
    scope: {
      callback: '&enter'
    },
    link: function (scope, element, attrs) {
       element.bind("mouseenter", function () {
          scope.$apply('callback()')
       })
     }
   }
});

演示:Plunker

答案 1 :(得分:4)

这是常见做法吗?

是的,这是常见做法,指令经常需要访问变量的$ scope,以及调用方法(如LoadMoreTweets)。

即使在official docs,他们也有例如......

scope.$watch(...)

...在指令内部(控制器可能正在对监视的变量进行更改)。

指令以这种方式与控制器通信是完全合适的。

您甚至可以将控制器本身(不仅仅是范围)注入指令的link方法。查看http://docs.angularjs.org/guide/directive的“链接功能”部分。

“控制器在所有指令之间共享,允许指令将控制器用作通信通道。”

我可以使用服务吗?

当然可以。问题是为什么?如果您正在使用单个页面(例如显示推文)并且控制器已经有$scope.tweets变量和$scope.loadMoreTweets方法,那么如果您尝试将服务粘贴到其中,那么您就会过度复杂化不需要。

另一方面,服务非常适合应用程序范围的数据,例如用户配置文件。如果你的指令需要访问当前登录的用户,那么通过服务来做这件事很有意义。

来自文档:

Angular服务是执行Web应用程序通用特定任务的单例,例如$ http服务,它提供对浏览器的XMLHttpRequest对象的低级访问。

如果您的应用程序范围内的任务最适合单身人士,请务必使用服务。如果您只需要从指令访问/修改$ scope,只需直接与控制器对话,或触发控制器可以响应的事件。

答案 2 :(得分:2)

调用外部范围函数是有风险的,因为它会对周围范围做出假设。如果指令在不同的上下文中使用会发生什么?

可重复使用的指令可以采用更好的[1]策略与外界沟通:

  • 将其依赖关系推迟到服务。这更适合系统范围的功能。我想这不适用于你的例子。
  • 定义包含某些&attr属性的隔离范围,该属性绑定到外部范围的表达式。该指令可以将该表达式称为其私有范围的方法。

作为第二个策略的一个例子,我修改了你的例子。请在此处查看http://plnkr.co/5uOBNu

var app = angular.module('twitterApp', []);
app.controller("AppCtrl", function ($scope) {
    $scope.loadMoreTweets = function() {
        alert("Loading tweets!");
    };
});

app.directive("specialEnter", function() {
    return {
        scope: {
            onEnter: '&'
        },
        link: function(scope, element, attrs) {
            element.bind("mouseenter", function() {
                scope.onEnter();
            });
        }
    };
});

<div ng-controller="AppCtrl">
    <div special-enter on-enter="loadMoreTweets()">Hover here!</div>
</div>

[1]“更好”,意在避免硬连线依赖。