Angular JS:当我们已经有了指令的控制器和作用域时,指令的链接函数需要什么?

我需要对范围和模板执行一些操作。似乎我可以在函数或函数中执行此操作(因为两者都可以访问范围)。linkcontroller

当我必须使用功能而不是控制器时,情况是什么时候?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


答案 1

在我最初与和功能的斗争并阅读了很多关于它们的信息之后,我认为现在我有了答案。linkcontroller

首先让我们明白

角度指令是如何工作的:

  • 我们从模板开始(作为字符串或加载到字符串中)

    var templateString = '<div my-directive>{{5 + 10}}</div>';

  • 现在,它被包装为一个角度元素templateString

    var el = angular.element(templateString);

  • 现在,我们用 编译它来取回链接函数。el$compile

    var l = $compile(el)

    这是发生的事情,

    • $compile遍历整个模板并收集它识别的所有指令。
    • 发现的所有指令都是递归编译的,并收集其函数。link
    • 然后,将所有函数包装在新函数中,并作为 返回。linklinkl
  • 最后,我们为这个(链接)函数提供函数,该函数进一步使用这个及其相应的元素执行包装的链接函数。scopelscope

    l(scope)

  • 这会将 作为新节点添加到 和 调用 中,这会将其监视添加到与 DOM 中的模板共享的作用域中。templateDOMcontroller

enter image description here

比较编译链接控制器

  • 每个指令只编译一次,并保留链接函数以供重用。因此,如果有适用于指令的所有实例的内容,则应在指令的功能内执行。compile

  • 现在,编译后,我们有函数,该函数在将模板附加到DOM时执行。因此,我们执行特定于指令的每个实例的所有内容。例如:附加事件根据范围改变模板等。link

  • 最后,控制器意味着在指令工作时(附加后)可以实时和被动地工作。因此:DOM

    (1)设置视图[V](即模板)后,带有链接。 是我们的 [M] 并且是 M V C 中的 [C]$scope$controller

    (2)通过设置手表,利用与$scope的双向绑定。

    (3) 监视应添加到控制器中,因为这是在运行时监视模板的内容。$scope

    (4)最后,还用于能够在相关指令之间进行通信。(如 https://docs.angularjs.org/guide/directivecontrollermyTabs)

    (5)确实,我们也可以在函数中完成所有这些操作,但它是关于关注点的分离link

因此,最后我们有以下完全适合所有部分的内容:

enter image description here


答案 2

为什么需要控制器

当您想要在 DOM 中嵌套指令并将 API 函数从父指令公开到嵌套指令时,和 之间的区别就会发挥作用。linkcontroller

文档中

最佳做法:当您想要向其他指令公开 API 时,请使用控制器。否则,请使用链接。

假设你想要有两个指令,并且你希望指令只出现在里面,而不是其他地方。my-formmy-text-inputmy-text-inputmy-form

在这种情况下,您将在定义指令时说,它需要使用 require 参数从 DOM 元素中获取控制器,如下所示:.现在,来自父元素的控制器将作为第四个参数进入函数,紧随其后。您可以调用该控制器上的函数并与父指令进行通信。my-text-inputparentrequire: '^myForm'injectedlink$scope, element, attributes

此外,如果未找到此类控制器,则会引发错误。

为什么要使用链接

如果正在定义 ,则无需使用该函数,因为 在 上可用。此外,在定义 和 时,确实需要注意两者的调用顺序 ( 之前执行)。linkcontroller$scopecontrollerlinkcontrollercontroller

但是,为了与Angular方式保持一致,大多数DOM操作和双向绑定使用通常在函数中完成,而子级和操作的API则在.这不是一个硬性规则,但这样做将使代码更加模块化,并有助于分离关注点(控制器将维护状态,函数将维护+外部绑定)。$watcherslink$scopecontrollerdirectivelinkDOM