'控制器','链接'和& # 39;编译# 39;函数在定义指令时

有些地方似乎使用控制器功能指令逻辑和其他使用链接。angular主页上的选项卡例子中,一个指令使用controller,另一个指令使用link。这两者之间有什么区别?

113433 次浏览

我将稍微扩展一下您的问题,并包括compile函数。

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

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

  • 控制器函数 -当另一个指令需要与该指令交互时必须使用。例如,在AngularJS的主页上,pane指令需要将自己添加到由tabs指令维护的范围中,因此tabs指令需要定义一个控制器方法(考虑API),以便pane指令可以访问/调用。有关制表符和窗格指令的更深入的解释,以及为什么制表符指令在其控制器上使用this(而不是$scope)创建函数,请参见'this'vs $scope在AngularJS控制器

通常,你可以将方法$watches等放入指令的控制器或链接函数中。控制器将首先运行,这有时很重要(请参阅小提琴,它记录了ctrl和link函数运行时带有两个嵌套指令)。正如Josh在评论中提到的,你可能想把作用域操作函数放在控制器中,只是为了与框架的其余部分保持一致。

作为Mark回答的补充,compile函数不能访问作用域,但是link函数可以。

我非常推荐这个视频;Misko Hevery (AngularJS之父)的写指令,在那里他描述了不同之处和一些技术。(编译函数和链接函数在视频中的14点41分中的区别)。

  1. 在编译之前运行代码:使用控制器
  2. 编译后运行代码:使用链接

Angular约定:在controller中写业务逻辑,在link中写DOM操作。

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

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

你想从“豹子”指令中获取动物。

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

编译函数 -

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

语法

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

控制器

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

预连接

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

  2. 你可以使用angular更新控制器中的dom。元素,但不建议这样做,因为该元素是在link函数中提供的

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

post-link

  1. 指令只有链接函数,angular会将该函数视为post链接

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