定义指令时“控制器”,“链接”和“编译”函数之间的区别


Answers:


635

我将扩大您的问题,并包括编译功能。

  • 编译功能 -用于模板 DOM操纵(即,tElement =模板元素的操纵),因此适用于与指令关联的模板的所有DOM克隆的操纵。(如果您还需要一个链接函数(或之前和之后的链接函数),并且定义了一个编译函数,则编译函数必须返回链接函数,因为'link'如果'compile'定义了该属性,则该属性将被忽略。)

  • 链接功能 -通常用于注册侦听器回调(即,$watch作用域上的表达式)以及更新DOM(即,对iElement =单个实例元素的操作)。克隆模板后执行。例如,在内<li ng-repeat...>,链接功能是在<li>已将模板(tElement)克隆(到iElement中)该特定<li>元素之后执行的。A $watch允许指令通知范围属性更改(范围与每个实例相关联),这允许指令将更新后的实例值呈现给DOM。

  • 控制器功能 -当另一个指令需要与此指令进行交互时,必须使用它。例如,在AngularJS主页上,窗格指令需要将其自身添加到tabs指令所维护的范围内,因此tabs指令需要定义一个窗格指令可以访问/调用的控制器方法(think API)。

    有关tabs和pane指令以及为什么tabs指令为什么使用this(而不是on $scope)在其控制器上创建函数的更深入的说明,请参阅AngularJS控制器中的'this'与$ scope

通常,您可以将方法$watches等放入指令的控制器或链接函数中。控制器将首先运行,这有时很重要(请参见该小提琴,该日志记录了ctrl和link函数使用两个嵌套指令运行的时间)。正如Josh在评论中提到的那样,您可能希望将范围操作功能放在控制器内,只是为了与框架的其余部分保持一致。


131
该解释应该在主要的AngularJS文档中或至少对其进行引用
Dogoku 2012年

7
这是一个有用的答案,但我认为很难阅读。也许更多的标点符号和较小的句子会有所帮助。总体而言,我感谢您的回答。
马蒂·科尔特斯

在存在“编译”属性的情况下,$ compiler会忽略“链接”属性。但是,如果存在“控制器”属性,该怎么办?“控制器”是否会使$ compiler忽略“链接”和“编译”属性中的一个或两个?是否可以和/或建议将“编译”与“控制器”一起使用?
卡尔·G

1
@CarlG,关于链接和编译,控制器属性的存在对$ compiler无效。您可以使用编译和控制器。
Mark Rajcok

1
“ DOM侦听器”不是“(例如,作用域上的$ watch表达式)”。一个监听DOM中的事件mouseover,另一个监听属性更改的范围。很大的区别。
德米特里·扎伊采夫


35
  1. 编译前运行代码:使用控制器
  2. 编译后运行代码:使用链接

角度约定:在控制器中编写业务逻辑,在链接中编写DOM操作。

除此之外,您可以从另一个指令的链接函数中调用一个控制器函数,例如,您有3个自定义指令

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>

并且您想从“豹”指令内部访问动物。

http://egghead.io/lessons/angularjs-directive-communication将有助于了解指令间通信


18
“编译前运行代码:使用控制器”。这是不正确的。compile将始终在之前 执行controller
Izhaki 2014年

您将(至少不能以一种简单的方式)从您的豹指令访问动物。子指令可以访问父指令中的控制器方法,但兄弟指令(如上例中所示)不能调用彼此的控制器。
本杰明·怀特

2
豹真的是豹的一种吗?另外,顺便说一句...您能否在指令中有一个链接-和-控制器?
科迪2014年

1
是的,豹子/美洲虎是豹。是的,您在指令中包含链接和控制器。
拉胡尔2014年

1
来自Angular开发人员指南:“最佳实践:要将API公开给其他指令时,请使用控制器。否则,请使用链接。”
马丁·范·德里尔

6

编译功能 -

  1. 在控制器和链接功能之前被调用。
  2. 在编译功能中,您拥有原始模板DOM,因此您可以在AngularJS创建它的实例之前以及在创建作用域之前对原始DOM进行更改。
  3. ng-repeat是完美的示例-原始语法是模板元素,HTML中的重复元素是实例
  4. 可以有多个元素实例,只有一个模板元素
  5. 范围尚不可用
  6. 编译函数可以返回函数和对象
  7. 返回一个(后链接)函数-等同于当编译函数为空时通过config对象的link属性注册链接函数。
  8. 返回具有通过pre和post属性注册的函数的对象-允许您控制在链接阶段何时应调用链接函数。请参阅下面有关预链接和后链接功能的信息。

句法

function compile(tElement, tAttrs, transclude) { ... }

控制者

  1. 在编译函数之后调用
  2. 范围在这里可用
  3. 可以通过其他指令访问(请参阅require属性)

预先连结

  1. 链接功能负责注册DOM侦听器以及更新DOM。克隆模板后执行。这是放置大多数指令逻辑的地方。

  2. 您可以使用angular.element在控制器中更新dom,但不建议这样做,因为link函数中提供了element

  3. 预链接功能用于实现当angular js已编译子元素但在任何子元素的post链接被调用之前运行的逻辑

链接后

  1. 仅具有链接功能的指令,角度将功能视为后链接

  2. post将在编译,控制器和预链接功能之后执行,因此这就是为什么它被认为是添加指令逻辑的最安全和默认位置的原因

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.