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

19 浏览
0 Comments

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

在作用域和模板上执行某些操作。似乎可以在link函数或controller函数中进行操作(因为两者都可以访问作用域)。\n什么情况下必须使用link函数而不是控制器?\n此外,我了解到link是非Angular世界的。因此,我可以使用$watch$digest$apply。\n当我们已经有控制器时,link函数的重要性是什么?

0
0 Comments

Angular JS中,指令(directive)的link函数的存在是因为它从不同的角度来看待问题,与MVC的角色分离不同。当我们想要跨越控制器/模型/视图(模板)的边界时,link函数是非常重要的。

为了将link函数放入上下文中,我们需要提到所有指令都经历的初始化过程:编译(Compile)和链接(Link)。编译阶段是指Angular遍历DOM以识别模板中的所有注册指令,并根据指令的规则(模板、替换、传递等)来转换DOM。如果存在,还会调用编译函数,最终得到一个编译后的模板函数。链接阶段是为了使视图动态化,Angular为每个指令运行一个链接函数。链接函数通常在DOM或模型上创建监听器,以保持视图和模型的同步。

link函数的参数包括scope、element和attrs。scope是一个Angular作用域对象,element是与指令匹配的jqLite封装元素,attrs是一个包含标准化属性名称及其对应值的对象。

link函数的一个示例可以在Angular官方文档的"Creating Custom Directives"中找到。这个示例展示了如何插入一个每秒刷新的"date-time"到页面中。

link函数的作用是允许我们对DOM进行操作,它可以执行一些不属于MVC的任务。在示例中,link函数中的updateTime函数用于更新DOM中的时间,同时还利用$timeout服务进行了定时更新,并在元素销毁时清除了定时器,以避免内存泄漏。

在代码中,我们也可以看到控制器(controller)的作用。控制器用于响应来自视图的模型更改。控制器负责将MVC中的视图和模型保持同步。与之相比,link函数则用于跨越控制器/模型/视图的边界,执行一些控制器无法完成的任务,如直接操作DOM。

在比较编译器(compiler)和链接函数(link)时,有人可能会问为什么需要链接函数,而我们已经有了控制器函数。实际上,控制器和链接函数在功能上是不同的,控制器用于对模型的更改做出响应,而链接函数用于执行一些更特定的任务,如操作DOM。

控制器和链接函数的具体概念可以在官方文档中找到。文档中提到,如果需要向其他指令公开API,则使用控制器。否则,使用链接函数。

总结一下,当需要执行一些超出MVC范围的任务时,链接函数是必要的。在一般情况下,控制器已经足够使用,但是当需要跨越控制器/模型/视图的边界时,链接函数为我们提供了额外的功能。这也是为什么Angular团队选择在框架中提供链接函数的原因。

0
0 Comments

AngularJS中指令的link函数和controller的区别在于当我们想要在DOM中嵌套指令并将父指令的API函数暴露给嵌套指令时。在定义指令时,我们可以使用require参数来指定需要从父DOM元素中获取一个控制器,例如require: '^myForm'。这样,父元素的控制器将作为第四个参数注入到link函数中,顺序为$scope、element、attributes。您可以在该控制器上调用函数并与父指令进行通信。如果找不到这样的控制器,将引发错误。

实际上,如果已经定义了controller,就没有真正需要使用link函数的必要性,因为$scope在controller上是可用的。此外,如果同时定义link和controller,需要小心考虑它们的执行顺序(controller在link之前执行)。

然而,按照Angular的方式,通常在link函数中进行大部分DOM操作和双向绑定,而将用于子指令和$scope操作的API放在controller中。这不是一个绝对的规则,但这样做会使代码更模块化,并有助于分离关注点(controller将维护指令状态,而link函数将维护DOM和外部绑定)。

从实践的角度来看,您应该始终将DOM操作放在link中,将业务逻辑放在controller中,这是Angular的约定。有些人会将这两者都放在link中,这样做是可以的,但有点违反了关注点分离的原则。总之,将DOM操作和业务逻辑完全放在link中比完全放在controller中更“安全”。

所以,为什么会有link的存在呢?实际上,没有任何问题发生在只定义controller的情况下(尽管需要注意controller和link的执行顺序)。应该将$scope操作放在controller中,将DOM操作和使用$watchers进行双向绑定放在link函数中,但这只是一个弱观点。

0
0 Comments

AngularJS中,指令的link函数是用来解决什么问题的呢?我们已经有了指令的controller和scope,为什么还需要link函数呢?

在阅读了很多关于link函数和controller函数的资料之后,我终于找到了答案。

首先,让我们来了解一下AngularJS指令的工作原理:

1. 我们首先有一个模板(可以是一个字符串或者加载到一个字符串中):

var templateString = '
{{5 + 10}}
';

2. 现在,将这个模板字符串包装成一个Angular元素:

var el = angular.element(templateString);

3. 使用$compile编译这个元素,得到link函数:

var l = $compile(el);

这里发生了什么:

- $compile会遍历整个模板,并收集所有它能识别的指令。

- 所有被发现的指令都会被递归编译,并且它们的link函数会被收集起来。

- 然后,所有的link函数会被包装在一个新的link函数中,并作为l返回。

4. 最后,我们将scope函数提供给这个link函数,这个link函数会进一步执行被包装的link函数,使用提供的scope和它们对应的元素:

l(scope);

5. 这将把模板作为一个新的节点添加到DOM中,并调用controller函数,controller函数会将其watch添加到与DOM中的模板共享的scope中。

下图展示了整个过程:

![enter image description here](https://i.stack.imgur.com/0PwGA.png)

对比compile、link和controller:

- 每个指令只会被编译一次,link函数会被保留以供复用。因此,如果有某些适用于指令的所有实例的内容,应该在指令的compile函数中执行。

- 现在,在编译之后,我们有了link函数,当将模板附加到DOM上时,link函数会被执行。因此,我们在link函数中执行那些对每个指令实例特定的操作,例如:添加事件、根据scope修改模板等。

- 最后,controller函数在指令在DOM上工作时应该是活动的和响应的。因此:

1. 在使用link设置了视图(即模板)之后,$scope是我们的M(Model),$controller是我们的C(Controller)。

2. 通过使用$scope来利用双向绑定,通过设置watch来实现。

3. $scope的watch应该在controller中添加,因为这是在运行时观察模板的对象。

4. 最后,controller还用于在相关指令之间进行通信(例如,参考AngularJS文档中的myTabs示例)。

5. 的确,我们也可以在link函数中完成所有这些操作,但这是关注点分离的问题。

因此,最后我们得到了完美契合的解决方案:

![diagram showing compilation flow in AngularJS](https://i.stack.imgur.com/SAFpN.png)

我还发现了这篇文章对于理解这里的执行顺序非常有用:[The nitty-gritty of compile and link functions inside AngularJS directives](http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives/)

很好的解释。值得一提的是,controller在link函数之前被调用。

controller在link函数之前被执行。

0