定义指令时,'controller','link'和'compile'函数之间的区别

use*_*259 391 javascript web-applications javascript-framework angularjs

有些地方似乎使用控制器功能用于指令逻辑而其他地方使用链接.角度主页上的选项卡示例使用控制器作为一个,并链接另一个指令.两者有什么区别?

Mar*_*cok 631

我将稍微扩展你的问题,并包括编译功能.

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

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

  • controller函数 - 当另一个指令需要与该指令交互时必须使用.例如,AngularJS主页上,窗格指令需要将自身添加到由标签指令维护的范围,因此标签指令需要定义一个控制器方法(认为API),该窗格指令可以访问/调用.

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

通常,您可以将方法$watches等放入指令的控制器或链接函数中.控制器将首先运行,这有时很重要(当ctrl和link函数使用两个嵌套指令运行时,请参阅此小提琴.正如Josh在评论中提到的那样,您可能希望将范围操作函数放在控制器中,以便与框架的其余部分保持一致.

  • 这个解释应该在主要的AngularJS文档中,或者至少是对它的引用 (131认同)
  • 这是一个信息丰富的答案,但我认为这很难阅读.也许更多的标点符号和更小的句子可以提供帮助.总的来说,我很感激答案. (7认同)

Pix*_*xic 56

作为Mark答案的补充,编译函数无法访问范围,但链接函数可以访问范围.

我真的推荐这个视频; 由Misko Hevery(AngularJS之父)撰写指令,描述差异和一些技巧.(视频14:41标记的编译功能和链接功能之间的差异).

  • +1是视频的链接.这是非常翔实的. (3认同)
  • http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/ (2认同)

Rah*_*hul 35

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

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

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

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>
Run Code Online (Sandbox Code Playgroud)

并且你想从"豹子"指令里面访问动物.

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

  • "在编译之前运行代码:使用控制器".这是不正确的; `compile`总是在*`controller`之前执行*. (18认同)
  • 豹子真的是一种黑豹吗?此外,在旁注...你有一个链接 - 和 - 指令中的控制器? (2认同)

Sun*_*arg 6

编译功能 -

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

句法

function compile(tElement, tAttrs, transclude) { ... }
Run Code Online (Sandbox Code Playgroud)

调节器

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

预先链接

  1. link函数负责注册DOM侦听器以及更新DOM.它在克隆模板后执行.这是大多数指令逻辑的用武之地.

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

  3. 预链接函数用于实现逻辑,该逻辑在角度js已经编译子元素但在调用任何子元素的post链接之前运行

后链接

  1. 只有链接函数的指令,angular将函数视为post link

  2. post将在编译,控制器和预链接函数之后执行,这就是为什么这被认为是添加指令逻辑的最安全和默认的地方