7

我一直在观看 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管视频

4

3 回答 3

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

于 2013-04-05T13:50:17.643 回答
4

这是常见的做法吗?

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

即使在官方文档中,他们也有类似..

scope.$watch(...)

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

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

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

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

但是我可以使用服务吗?

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

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

从文档:

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

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

于 2013-04-05T13:04:16.110 回答
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] “更好”在某种意义上避免了硬性依赖。

于 2013-04-05T13:46:26.000 回答