我一直在观看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();
})
}
}
我想知道的一件事是,本示例中的指令应该与控制器对话,还是创建服务然后让指令与服务进行通信是一种更好的编程习惯?我想我仍然不确定指令以这种方式与控制器通信是否是常见做法。
答案 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]“更好”,意在避免硬连线依赖。