Angular JS:当我们已经有了指令的控制器和范围的时候,这个指令的链接函数需要什么?

我需要在范围和模板上执行一些操作。 看来我可以在link函数或controller函数中这样做(因为两者都可以访问范围)。

什么时候需要使用linkfunction而不是控制器?

 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是无棱angular的世界。 所以,我可以使用$watch$digest$apply

当我们已经有了控制器的时候, link函数的意义是什么?

在我最初linkcontrollerfunction的斗争和阅读了很多关于他们,我想现在我有答案。

首先让我们了解

angular度指令如何工作:

  • 我们从一个模板开始(作为一个string或者加载到一个string)

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

  • 现在,这个templateString被封装成一个angular度元素

    var el = angular.element(templateString);

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

    var l = $compile(el)

    这是发生了什么,

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

    l(scope)

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

在这里输入图像描述

比较编译链接 vs 控制器

  • 每个指令只编译一次, 链接function保留重用。 因此,如果在指令的compile函数内部有适用于指令的所有实例的内容。

  • 现在,在编译之后,我们有linkfunction,它是在将模板附加到DOM时执行的 。 因此,我们执行每个指令的每个实例的具体内容。 例如: 附加事件根据范围来变更模板等。

  • 最后, 控制器意味着可以是生动的和被动的,而指令在DOM (在被连接之后)。 因此:

    (1)用链接build立视图[ V ](即模板)。 $scope是我们的[ M ], $controllerMVC中的 [ C ]

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

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

    (4)最后, controller也被用来在相关指令之间进行通信。 (像https://docs.angularjs.org/guide/directive中的; myTabs示例)

    (5)的确,我们可以在linkfunction中完成所有这些工作,但是关于问题的分离

因此,最后我们有以下几点完美地适合所有的部分:

在这里输入图像描述

为什么需要控制器

linkcontroller的区别在于你想要在你的DOM中嵌套指令,并且把父指令的API函数暴露给嵌套指令。

从文档 :

最佳实践:当您想要将API暴露给其他指令时,请使用控制器。 否则使用链接。

假设你想有两个指令my-formmy-text-input并且你希望my-text-input指令只出现在my-form和其他地方。

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

而且,如果找不到这样的控制器,就会出现错误。

为什么要使用链接

由于$scopecontroller上可用,因此如果定义了controller则不需要使用linkfunction。 而且,在定义linkcontroller ,还需要注意两者的调用顺序( controller在之前执行)。

然而,按照Angular的方式 ,大多数使用$watchers DOM操作和2-way绑定通常是在link函数中完成的,而用于儿童的API和$scope操作在controller完成。 这不是一个硬性规则,但这样做会使代码更加模块化,并有助于分离关注点(控制器将保持directive状态,并且linkfunction将维护DOM +外部绑定)。

controllerfunction/对象表示抽象模型 – 视图 – 控制器(MVC)。 虽然没有什么新的MVC写,它仍然是angular的最重要的优势:将关注分成更小的块。 就是这样,所以如果您需要对来自“ ViewController Model更改做出反应,那么这是正确的人选

关于linkfunction的故事是不同的,它是从不同的angular度来看MVC。 一旦我们想要跨越controller/model/view (模板)的界限,真的很重要。

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

 function link(scope, element, attrs) { 
  • 范围是一个angular度范围对象。
  • 元素是该指令匹配的jqLit​​e-wrapped元素。
  • attrs是具有标准化属性名称及其对应值的对象。

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

编译阶段 (链接的姐妹,让我们在这里提到一个清晰的图片):

在这个阶段,Angular走DOM去识别模板中的所有注册指令。 对于每个指令,然后根据指令的规则(模板,replace,transclude等等)转换DOM,并在编译函数存在的情况下调用它。 结果是编译模板函数,

链接阶段

为了使视图dynamic化,Angular为每个指令运行一个链接函数。 链接function通常在DOM或模型上创build侦听器。 这些监听器始终保持视图和模型同步。

如何使用link一个很好的例子可以在这里find: 创build自定义指令 。 请参阅示例: 创build操纵DOM的指令,该指令在页面中插入“date – 时间”,每秒刷新一次。

从上面的丰富源代码只是一个非常短的片段,展示了真正的DOM操作。 有$ hook服务的挂钩函数,并且它的析构函数调用清除,以避免内存泄漏

 .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); }); ... 

我会在现有的答案中再补充一点。 链接function保证在DOM准备就绪挂钩,这样在使用链接时可以考虑。