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

IT技术 javascript angularjs web-applications javascript-framework
2021-02-06 00:18:58

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

4个回答

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

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

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

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

    有关选项卡和窗格指令的更深入解释,以及为什么选项卡指令使用this(而不是 on $scope在其控制器上创建函数,请参阅AngularJS 控制器中的“this”与 $scope

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

这个解释应该在主要的 AngularJS 文档中或者至少是对它的引用
2021-03-27 00:18:58
@CarlG,控制器属性的存在对 $compiler 的链接和编译没有影响。您可以使用编译和控制器。
2021-04-02 00:18:58
“DOM 侦听器”不是“(即作用域上的 $watch 表达式)”。一个监听 DOM 之类的事件mouseover另一个监听属性更改的范围。巨大差距。
2021-04-02 00:18:58
这是一个内容丰富的答案,但我认为它很难阅读。也许更多的标点符号和更小的句子会有所帮助。总的来说,我很感激你的回答。
2021-04-08 00:18:58
$compiler 在存在 'compile' 属性时忽略 'link' 属性。但是如果存在“控制器”属性呢?“控制器”是否会导致 $compiler 忽略“链接”和“编译”属性之一或两者?是否可以和/或建议将“编译”与“控制器”一起使用?
2021-04-10 00:18:58

作为对 Mark 答案的补充,compile 函数无法访问范围,但链接函数可以。

我真的很推荐这个视频;由 Misko Hevery(AngularJS 之父)编写的指令,在那里他描述了差异和一些技术。视频14:41 标记处编译函数和链接函数的区别)。

2021-03-16 00:18:58
+1 用于视频链接。这是非常有用的信息。
2021-03-28 00:18:58
  1. 编译前运行代码:使用控制器
  2. 编译后运行代码:使用链接

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

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

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

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

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

是的,豹/美洲虎是黑豹。是的,您在指令中有链接和控制器。
2021-03-19 00:18:58
来自 Angular 开发人员指南:“最佳实践:当您想将 API 公开给其他指令时使用控制器。否则使用链接。”
2021-03-23 00:18:58
豹真的是豹的一种吗?另外,顺便提一下……你能有一个链接——和——指令中的控制器吗?
2021-04-02 00:18:58
您将无法(至少不能以直接的方式)从您的 leopard 指令访问动物。子指令可以访问父指令中的控制器方法,但同级指令(如上面的示例)不能调用彼此的控制器。
2021-04-10 00:18:58
“编译前运行代码:使用控制器”。这是不正确的;compile将始终在之前 执行controller
2021-04-11 00:18:58

编译功能——

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

句法

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

控制器

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

预链接

  1. link 函数负责注册 DOM 监听器以及更新 DOM。它在模板被克隆后执行。这是大多数指令逻辑将被放置的地方。

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

  3. Pre-link 函数用于实现在 angular js 已经编译了子元素但在调用任何子元素的 post 链接之前运行的逻辑

后链接

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

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