首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Angular JS:当我们已经有了带作用域的指令控制器时,还需要指令的链接函数吗?

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

Stack Overflow用户
提问于 2013-11-16 20:34:12
回答 3查看 164.9K关注 0票数 211

我需要对作用域和模板执行一些操作。似乎我可以在link函数或controller函数中执行此操作(因为这两个函数都可以访问作用域)。

什么情况下必须使用link函数而不是控制器?

代码语言:javascript
复制
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函数的意义是什么呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-18 21:18:29

在我的初始linkcontroller函数作斗争并阅读了大量关于它们的内容之后,我想我现在有了答案。

首先让了解

简而言之,angular指令是如何工作的:

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

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

  • Now,此templateString被包装为angular元素

var el = angular.element(templateString);

  • With el,现在我们用$compile编译它,以返回链接函数。

var l = $compile(el)

事情是这样的,

代码语言:javascript
复制
- `$compile` walks through the whole template and collects all the directives that it recognizes.
- All the directives that are discovered are **compiled recursively** and their `link` functions are collected.
- Then, all the `link` functions are wrapped in a new `link` function and returned as `l`.

  • 最后,我们为这个l (链接)函数提供了scope函数,该函数进一步使用这个scope及其对应的元素执行包装的链接函数。

l(scope)

  • This将template作为新节点添加到DOM中,并调用controller,后者将其监视添加到与DOM中的模板共享的scope中。

比较编译与链接与控制器:

  • 每条指令只编译一次,并保留链接函数以备重用。因此,如果有一些适用于编译后应该在指令的compile function.
  • Now,中执行的指令的所有实例,我们有link函数,该函数在将模板附加到DOM时执行。因此,我们执行特定于指令的每个实例的所有操作。例如:attached events,根据作用域改变模板,控制器应该在指令在DOM上工作时是有效的和反应的(在附加之后)。因此:

(1)设置了带链接的视图之后。$scope是我们的M,$controller是我们在M V C中的C

(2)通过设置监视来利用与$scope的双向绑定。

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

(4)最后,还使用了controller来实现相关指令之间的通信。(就像https://docs.angularjs.org/guide/directive中的myTabs示例)

(5)我们也可以在concerns.的link函数中完成所有这些工作,但这是关于分离的

因此,我们最终得到了以下内容,它完美地满足了所有的需求:

票数 312
EN

Stack Overflow用户

发布于 2013-11-16 20:59:31

为什么需要控制器

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

docs

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

假设您希望有两个指令my-formmy-text-input,并且希望my-text-input指令只出现在my-form内部,而不出现在其他地方。

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

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

为什么要使用link

如果正在定义link,则不需要使用controller函数,因为$scopecontroller上可用。此外,同时定义linkcontroller时,需要注意这两者的调用顺序(controller是在执行之前执行的)。

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

票数 84
EN

Stack Overflow用户

发布于 2013-11-17 02:22:42

controller函数/对象表示一个抽象的模型-视图-控制器。虽然关于MVC没有什么新东西可写,但它仍然是angular最重要的优点:将关注点拆分成更小的部分。仅此而已,如果您需要对来自ViewModel更改做出反应,那么Controller是做这项工作的合适人选。

关于link函数的故事是不同的,它来自不同的角度。一旦我们想要跨越controller/model/view (模板)的边界,这是非常必要的。

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

代码语言:javascript
复制
function link(scope, element, attrs) {

  • scope是一个角度作用域,object.
  • element是jqLite包装的元素,此指令matches.
  • attrs是一个具有规范化属性名称及其相应值的对象。

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

编译阶段( link的姊妹,让我们在这里提到它以获得一个清晰的画面):

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

链路阶段

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

在这里可以找到如何使用link的一个很好的例子:Creating Custom Directives。参见示例:创建一个操纵DOM的指令,该指令将一个“日期-时间”插入到页面中,每秒刷新一次。

上面富源代码中的一小段代码展示了对DOM的实际操作。$timeout服务有钩子函数,并在其析构函数调用中将其清除,以避免内存泄漏

代码语言:javascript
复制
.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);
 });

 ...
票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20018507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档