我需要对作用域和模板执行一些操作。似乎我可以在link
函数或controller
函数中执行此操作(因为这两个函数都可以访问作用域)。
什么情况下必须使用link
函数而不是控制器?
angular.module('myApp').directive('abc', function($timeout) {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: true,
link: function(scope, elem, attr) { /* link function */ },
controller: function($scope, $element) { /* controller function */ }
};
}
另外,我知道link
是一个非角度的世界。因此,我可以使用$watch
、$digest
和$apply
。
既然我们已经有了控制器,那么link
函数的意义是什么呢?
发布于 2014-05-18 21:18:29
在我的初始与link
和controller
函数作斗争并阅读了大量关于它们的内容之后,我想我现在有了答案。
首先让了解,
简而言之,angular指令是如何工作的:
var templateString = '<div my-directive>{{5 + 10}}</div>';
templateString
被包装为angular元素var el = angular.element(templateString);
el
,现在我们用$compile
编译它,以返回链接函数。var l = $compile(el)
事情是这样的,
- `$compile` walks through the whole template and collects all the directives that it recognizes.
- All the directives that are discovered are **compiled recursively** and their `link` functions are collected.
- Then, all the `link` functions are wrapped in a new `link` function and returned as `l`.
l
(链接)函数提供了scope
函数,该函数进一步使用这个scope
及其对应的元素执行包装的链接函数。l(scope)
template
作为新节点添加到DOM
中,并调用controller
,后者将其监视添加到与DOM中的模板共享的scope中。
比较编译与链接与控制器:
compile
function.link
函数,该函数在将模板附加到DOM时执行。因此,我们执行特定于指令的每个实例的所有操作。例如:attached events,根据作用域改变模板,控制器应该在指令在DOM
上工作时是有效的和反应的(在附加之后)。因此:(1)设置了带链接的视图之后。$scope
是我们的M,$controller
是我们在M V C中的C
(2)通过设置监视来利用与$scope的双向绑定。
(3)预计将在控制器中添加$scope
监视,因为这是在运行时监视模板的内容。
(4)最后,还使用了controller
来实现相关指令之间的通信。(就像https://docs.angularjs.org/guide/directive中的myTabs
示例)
(5)我们也可以在concerns.的link
函数中完成所有这些工作,但这是关于分离的
因此,我们最终得到了以下内容,它完美地满足了所有的需求:
发布于 2013-11-16 20:59:31
为什么需要控制器
当您想要在DOM中嵌套指令并将link
函数从父指令公开到嵌套指令时,controller
和API之间的区别就开始发挥作用。
从docs
最佳实践:当您想要将一个API暴露给其他指令时,请使用控制器。否则,请使用link。
假设您希望有两个指令my-form
和my-text-input
,并且希望my-text-input
指令只出现在my-form
内部,而不出现在其他地方。
在这种情况下,您将在定义指令my-text-input
时使用parent
参数说明它需要来自requires元素的控制器,例如:require: '^myForm'
。现在,父元素中的控制器将被injected
到link
函数中,作为$scope, element, attributes
之后的第四个参数。您可以调用该控制器上的函数并与父指令进行通信。
此外,如果找不到这样的控制器,则会引发错误。
为什么要使用link
如果正在定义link
,则不需要使用controller
函数,因为$scope
在controller
上可用。此外,同时定义link
和controller
时,需要注意这两者的调用顺序(controller
是在执行之前执行的)。
然而,为了与角度方式保持一致,大多数使用$watchers
的DOM操作和双向绑定通常是在link
函数中完成的,而对子对象和$scope
操作的API是在controller
中完成的。这不是一个严格的规则,但这样做将使代码更加模块化,并有助于分离关注点(控制器将维护directive
状态,link
函数将维护DOM
+外部绑定)。
发布于 2013-11-17 02:22:42
controller
函数/对象表示一个抽象的模型-视图-控制器。虽然关于MVC没有什么新东西可写,但它仍然是angular最重要的优点:将关注点拆分成更小的部分。仅此而已,如果您需要对来自View
的Model
更改做出反应,那么Controller
是做这项工作的合适人选。
关于link
函数的故事是不同的,它来自不同的角度。一旦我们想要跨越controller/model/view
(模板)的边界,这是非常必要的。
让我们从传递给link
函数的参数开始:
function link(scope, element, attrs) {
为了将link
放到上下文中,我们应该提到所有指令都在经历这个初始化过程步骤:编译、链接。摘自Brad Green和Shyam Seshadri的书Angular JS
编译阶段( link的姊妹,让我们在这里提到它以获得一个清晰的画面):
在此阶段,Angular遍历DOM以识别模板中所有注册的指令。对于每个指令,它会根据指令的规则(template、replace、transclude等)转换DOM,并调用compile函数(如果存在)。结果是编译后的模板函数,
链路阶段
使视图成为动态视图,然后为每个指令运行一个链接函数。链接函数通常在DOM或模型上创建侦听器。这些侦听器使视图和模型始终保持同步。
在这里可以找到如何使用link
的一个很好的例子:Creating Custom Directives。参见示例:创建一个操纵DOM的指令,该指令将一个“日期-时间”插入到页面中,每秒刷新一次。
上面富源代码中的一小段代码展示了对DOM的实际操作。$timeout服务有钩子函数,并在其析构函数调用中将其清除,以避免内存泄漏
.directive('myCurrentTime', function($timeout, dateFilter) {
function link(scope, element, attrs) {
...
// the not MVC job must be done
function updateTime() {
element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM
}
function scheduleUpdate() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
scheduleUpdate(); // schedule the next update
}, 1000);
}
element.on('$destroy', function() {
$timeout.cancel(timeoutId);
});
...
https://stackoverflow.com/questions/20018507
复制相似问题