Angular JS:当指令的控制器具有范围时,指令的链接功能需要什么?

Yug*_*dle 193 javascript angularjs angularjs-directive

我需要对范围和模板执行一些操作.似乎我可以在link函数或controller函数中执行此操作(因为它们都可以访问范围).

什么时候我必须使用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 */ }
    };
}
Run Code Online (Sandbox Code Playgroud)

另外,我明白这link是非角度的世界.所以,我可以使用$watch,$digest$apply.

link当我们已经拥有控制器时,该功能有什么意义?

Yug*_*dle 293

我经过最初的一起奋斗linkcontroller功能,阅读了很多关于他们的,我想现在我找到了答案.

首先让我们理解,

角度指令如何工作简而言之:

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

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

  • 现在,它templateString被包裹为角元素

    var el = angular.element(templateString);

  • 有了el,现在我们编译它$compile以取回链接功能.

    var l = $compile(el)

    这是发生了什么,

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

    l(scope)

  • 这会将template作为新节点添加到DOM并调用controller,这会将其监视添加到与DOM中的模板共享的范围.

在此输入图像描述

比较编译链接控制器:

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

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

  • 最后,当指令在(在连接之后)工作时,控制器可用于实时和被动DOM.因此:

    (1 )用链接设置视图[ V ](即模板)后.$scope是我们的[ M ]并且$controller是我们在MVC中的 [ C ]

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

    (3)$scope预计手表会被添加到控制器中,因为这是在运行期间观看模板的内容.

    (4)最后,controller也用于能够在相关指令之间进行通信.(myTabs例如https://docs.angularjs.org/guide/directive中的示例)

    (5)确实,我们可以在link功能中完成所有这些,但关于关注点的分离.

因此,最后我们有以下完美契合所有部分:

在此输入图像描述

  • **控制器在链接之前执行** (37认同)
  • 令我愤怒的是Stack Overflow要求编辑至少6个字符,因此不允许我在这个答案中纠正let的拼写. (10认同)
  • 我还发现这篇文章对于理解这里的执行顺序很有用:[AngularJS指令中编译和链接函数的细节](http://www.jvandemo.com/the-nitty-gritty-of-compile -and-链路功能-内部-angularjs-指令/) (4认同)
  • 很棒的解释.想提一下控制器在链接功能之前被调用. (4认同)

mus*_*_ut 74

为什么需要控制器

之间的差异linkcontroller当你想在你的DOM巢指令和从父指令嵌套那些暴露的API函数的用武之地.

来自文档:

最佳实践:当您希望将API公开给其他指令时,请使用控制器.否则使用链接.

假设您希望有两个指令my-form,my-text-input并且您希望my-text-input指令仅在内部my-form和其他地方出现.

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

此外,如果找不到这样的控制器,则会引发错误.

为什么要使用链接

没有真正需要使用该link函数,如果一个人正在定义,controller因为它$scope是可用的controller.此外,虽然限定两个linkcontroller,一个确实需要小心关于两个的调用顺序(controller之前执行).

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


Rad*_*ler 17

controller功能/对象表示一个抽象模型-视图-控制器(MVC).虽然没有什么新东西可以写MVC,但它仍然是角度最重要的优点:将问题分成更小的部分.就是这样,仅此而已,所以如果你需要对Model来自View这些工作Controller的合适人员作出反应.

关于link功能的故事是不同的,它来自不同的视角,然后是MVC.一旦我们想跨越controller/model/view (模板)的界限,这是非常重要的.

让我们从传递给link函数的参数开始:

function link(scope, element, attrs) {
Run Code Online (Sandbox Code Playgroud)
  • scope是一个Angular范围对象.
  • element是此指令匹配的jqLit​​e-wrapped元素.
  • attrs是一个具有规范化属性名称及其对应值的对象.

为了link进入上下文,我们应该提到所有指令都经历了这个初始化过程的步骤:编译,链接.Brad Green和Shyam Seshadri的书摘录Angular JS:

编译阶段(链接的姐妹,我们在这里提一下以获得清晰的图片):

在此阶段,Angular遍历DOM以识别模板中的所有已注册指令.对于每个指令,它然后根据指令的规则(模板,替换,转换等)转换DOM,并调用编译函数(如果存在).结果是编译模板函数,

链接阶段:

为了使视图动态化,Angular然后为每个指令运行链接函数.链接函数通常在DOM或模型上创建侦听器.这些侦听器始终使视图和模型保持同步.

link可以在此处找到如何使用的一个很好的示例:创建自定义指令.请参阅示例:创建操纵DOM的指令,该指令在页面中插入"日期时间",每秒刷新一次.

只是上面这个丰富资源的一个非常简短的片段,显示了DOM的真正操作.$ timeout服务有一个钩子函数,并且它在析构函数调用中被清除以避免内存泄漏

.directive('myCurrentTime', function($timeout, dateFilter) {

 function link(scope, element, attrs) {

 ...

 // the not MVC job must be done
 function updateTime() {
   element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM
 }

 function scheduleUpdate() {
   // save the timeoutId for canceling
   timeoutId = $timeout(function() {
     updateTime(); // update DOM
     scheduleUpdate(); // schedule the next update
   }, 1000);
 }

 element.on('$destroy', function() {
   $timeout.cancel(timeoutId);
 });

 ...
Run Code Online (Sandbox Code Playgroud)

  • 你似乎比较了`compiler`和`link`.当我们已经有了`controller`时,他们的问题是问为什么`link` (3认同)