定义指令时,“控制器”,“链接”和“编译”function之间的区别
有些地方似乎将控制器function用于指令逻辑,而其他地方则使用链接。 angular度主页上的选项卡示例将控制器用于一个,并链接另一个指令。 两者有什么区别?
我打算扩大你的问题,也包括编译function。
-
编译函数 – 用于模板 DOM操作(即,tElement = template元素的操作),因此适用于与指令相关联的模板的所有DOM克隆的操作。 (如果你还需要链接函数(或者前后链接函数),并且你定义了一个编译函数,编译函数必须返回链接函数,因为如果
'compile'
属性是'link'
定义。) -
链接函数 – 通常用于注册监听器callback(即范围内的
$watch
expression式)以及更新DOM(即iElement =单个实例元素的操作)。 它在模板被克隆后执行。 例如,在<li ng-repeat...>
,链接函数在<li>
模板(tElement)被克隆到(iElement)特定的<li>
元素之后执行。$watch
允许指令被通知范围属性更改(范围与每个实例关联),这允许指令将更新的实例值呈现给DOM。 -
控制器function – 当另一个指令需要与此指令交互时必须使用。 例如,在AngularJS主页上,窗格指令需要将自身添加到由tabs指令维护的范围中,因此tabs指令需要定义窗格指令可以访问/调用的控制器方法(think API)。
有关选项卡和窗格指令的更深入的解释,以及为什么tabs指令使用
this
(而不是$scope
)在其控制器上创build一个函数,请参阅AngularJS控制器中的“this”和$ scope 。
通常,您可以将方法$watches
等放入指令的控制器或链接函数中。 控制器将首先运行,这有时很重要(当使用两个嵌套指令运行ctrl和link函数时,请参阅此日志logging)。 正如Josh在评论中提到的那样,为了与框架的其他部分保持一致,您可能需要将范围操作函数放在控制器中。
作为Mark的答案的补充,编译函数不能访问范围,但是链接函数可以。
我真的推荐这个video; 由Misko Hevery 撰写指令 (AngularJS的父亲),他描述了差异和一些技巧。 ( video中14:41标记的编译function和链接function的区别)
- 编译前运行代码:使用控制器
- 编译后运行代码:使用Link
Angular约定:在链接中写入控制器和DOM操作的业务逻辑。
除此之外,您可以从另一个指令的链接函数调用一个控制器函数。例如,您有3个自定义指令
<animal> <panther> <leopard></leopard> </panther> </animal>
你想从“豹”指令的内部访问动物。
http://egghead.io/lessons/angularjs-directive-communication将有助于了解有关指导间的沟通;
编译function –
- 在控制器和链接function之前被调用。
- 在编译function中,你有原始的模板DOM,所以你可以在AngularJS创build一个实例之前,在创build一个范围
- ng-repeat就是一个很好的例子 – 原始语法是模板元素,HTML中的重复元素是实例
- 可以有多个元素实例和只有一个模板元素
- 范围尚不可用
- 编译函数可以返回函数和对象
- 返回一个(后链接)函数 – 当编译函数为空时,相当于通过configuration对象的链接属性注册链接函数。
- 返回一个具有通过前后属性注册的函数的对象 – 允许您控制何时在链接阶段调用链接函数。 请参阅下面有关预链接和后链接function的信息。
句法
function compile(tElement, tAttrs, transclude) { ... }
调节器
- 在编译函数之后调用
- 范围在这里可用
- 可以通过其他指令访问(请参阅require属性)
预先链接
-
链接函数负责注册DOM监听器以及更新DOM。 它在模板被克隆后执行。 这是大多数指令逻辑将放在哪里。
-
您可以使用angular.element更新控制器中的dom,但不build议这样做,因为元素在链接function中提供
-
预链接function用于实现在angularjs已经编译子元素但在子元素的任何后链接被调用之前运行的逻辑
后链接
-
只有链接function的指令,将angular色视为后链接
-
后编译,控制器和预链接function后,将执行这个,所以这就是为什么这被认为是最安全和默认的地方添加您的指令逻辑
关于控制器的附加内容
控制器的签名是( 从文档 ):
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
最后一个是我认为重要的。 由于您可以通过使用控制器注入$ location,$ anchorScroll等varibales到指令。 据我所知,他们不具备链接function。