[英]Angular JS: What is the need of the directive’s link function when we already had directive’s controller with scope?
I need to perform some operations on scope and the template.我需要对范围和模板执行一些操作。 It seems that I can do that in either the
link
function or the controller
function (since both have access to the scope).似乎我可以在
link
函数或controller
函数中做到这一点(因为两者都可以访问范围)。
When is it the case when I have to use link
function and not the 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 */ }
};
}
Also, I understand that link
is the non-angular world.另外,我知道
link
是非角度世界。 So, I can use $watch
, $digest
and $apply
.所以,我可以使用
$watch
、 $digest
和$apply
。
What is the significance of the link
function, when we already had controller?当我们已经有了控制器时,
link
功能的意义是什么?
After my initial struggle with the link
and controller
functions and reading quite a lot about them, I think now I have the answer.在我对
link
和controller
功能的最初挣扎并阅读了很多关于它们的内容之后,我想现在我有了答案。
First lets understand ,首先让我们了解一下,
How do angular directives work in a nutshell:简而言之,角度指令是如何工作的:
We begin with a template (as a string or loaded to a string)我们从模板开始(作为字符串或加载到字符串)
var templateString = '<div my-directive>{{5 + 10}}</div>';
Now, this templateString
is wrapped as an angular element现在,这个
templateString
被包装成一个角度元素
var el = angular.element(templateString);
With el
, now we compile it with $compile
to get back the link function.使用
el
,现在我们用$compile
编译它以取回链接函数。
var l = $compile(el)
Here is what happens,这是发生的事情,
$compile
walks through the whole template and collects all the directives that it recognizes. $compile
遍历整个模板并收集它识别的所有指令。link
functions are collected.link
函数。link
functions are wrapped in a new link
function and returned as l
.link
函数都包装在一个新的link
函数中并作为l
返回。 Finally, we provide scope
function to this l
(link) function which further executes the wrapped link functions with this scope
and their corresponding elements.最后,我们为这个
l
(链接)函数提供scope
函数,该函数进一步执行具有此scope
及其相应元素的包装链接函数。
l(scope)
This adds the template
as a new node to the DOM
and invokes controller
which adds its watches to the scope which is shared with the template in DOM.这会将
template
作为新节点添加到DOM
并调用controller
, controller
将其监视添加到与 DOM 中的模板共享的范围。
Comparing compile vs link vs controller :比较编译vs链接vs控制器:
Every directive is compiled only once and link function is retained for re-use.每个指令只编译一次,链接函数被保留以供重用。 Therefore, if there's something applicable to all instances of a directive should be performed inside directive's
compile
function.因此,如果有一些适用于指令的所有实例的东西应该在指令的
compile
函数中执行。
Now, after compilation we have link
function which is executed while attaching the template to the DOM .现在,编译后我们有
link
函数,该函数在将模板附加到DOM 时执行。 So, therefore we perform everything that is specific to every instance of the directive.因此,我们执行针对指令的每个实例的所有操作。 For eg: attaching events , mutating the template based on scope , etc.
例如:附加事件,基于范围改变模板等。
Finally, the controller is meant to be available to be live and reactive while the directive works on the DOM
(after getting attached).最后,当指令在
DOM
(附加后),控制器是可用的。 Therefore:因此:
(1) After setting up the view[ V ] (ie template) with link. (1) 设置好带有链接的视图[ V ](即模板)后。
$scope
is our [ M ] and $controller
is our [ C ] in MVC $scope
是我们的 [ M ] 而$controller
是我们在MVC 中的[ C ]
(2) Take advantage the 2-way binding with $scope by setting up watches. (2) 通过设置监视来利用$scope的2 向绑定。
(3) $scope
watches are expected to be added in the controller since this is what is watching the template during run-time. (3)
$scope
watch 预计会被添加到控制器中,因为这是在运行时监视模板的内容。
(4) Finally, controller
is also used to be able to communicate among related directives. (4) 最后,
controller
还用于能够在相关指令之间进行通信。 (Like myTabs
example in https://docs.angularjs.org/guide/directive ) (就像https://docs.angularjs.org/guide/directive 中的
myTabs
示例)
(5) It's true that we could've done all this in the link
function as well but its about separation of concerns . (5) 确实,我们也可以在
link
函数中完成所有这些,但它是关于关注点分离的。
Therefore, finally we have the following which fits all the pieces perfectly :因此,最后我们有以下完美适合所有部分的内容:
The difference between link
and controller
comes into play when you want to nest directives in your DOM and expose API functions from the parent directive to the nested ones.当您想在 DOM 中嵌套指令并将 API 函数从父指令暴露给嵌套指令时,
link
和controller
之间的区别就开始发挥作用了。
Best Practice: use controller when you want to expose an API to other directives.
最佳实践:当您想向其他指令公开 API 时使用控制器。 Otherwise use link.
否则使用链接。
Say you want to have two directives my-form
and my-text-input
and you want my-text-input
directive to appear only inside my-form
and nowhere else.假设您希望有两个指令
my-form
和my-text-input
并且您希望my-text-input
指令仅出现在my-form
而不出现在其他任何地方。
In that case, you will say while defining the directive my-text-input
that it requires a controller from the parent
DOM element using the require argument, like this: require: '^myForm'
.在这种情况下,您将在定义指令
my-text-input
使用 require 参数说它需要来自parent
DOM 元素的控制器,例如: require: '^myForm'
。 Now the controller from the parent element will be injected
into the link
function as the fourth argument, following $scope, element, attributes
.现在来自父元素的控制器将作为第四个参数
injected
到link
函数中,紧跟在$scope, element, attributes
。 You can call functions on that controller and communicate with the parent directive.您可以调用该控制器上的函数并与父指令进行通信。
Moreover, if such a controller is not found, an error will be raised.此外,如果找不到这样的控制器,则会引发错误。
There is no real need to use the link
function if one is defining the controller
since the $scope
is available on the controller
.如果定义
controller
则没有真正需要使用link
功能,因为$scope
在controller
上可用。 Moreover, while defining both link
and controller
, one does need to be careful about the order of invocation of the two ( controller
is executed before).此外,在定义
link
和controller
,确实需要注意两者的调用顺序( controller
是在之前执行的)。
However, in keeping with the Angular way , most DOM manipulation and 2-way binding using $watchers
is usually done in the link
function while the API for children and $scope
manipulation is done in the controller
.然而,为了与Angular 的方式保持一致,大多数使用
$watchers
DOM 操作和 2 路绑定通常在link
函数中完成,而子 API 和$scope
操作在controller
完成。 This is not a hard and fast rule, but doing so will make the code more modular and help in separation of concerns (controller will maintain the directive
state and link
function will maintain the DOM
+ outside bindings).这不是一个硬性规定,但这样做会使代码更加模块化并有助于分离关注点(控制器将维护
directive
状态, link
函数将维护DOM
+ 外部绑定)。
The controller
function/object represents an abstraction model-view-controller (MVC). controller
函数/对象表示抽象模型-视图-控制器 (MVC)。 While there is nothing new to write about MVC, it is still the most significant advanatage of angular: split the concerns into smaller pieces.虽然关于 MVC 没有什么可写的,但它仍然是 angular 最重要的优点:将关注点分成更小的部分。 And that's it, nothing more, so if you need to react on
Model
changes coming from View
the Controller
is the right person to do that job.就是这样,仅此而已,因此,如果您需要对来自
View
的Model
更改做出反应,则Controller
是完成这项工作的合适人选。
The story about link
function is different, it is coming from different perspective then MVC.关于
link
功能的故事是不同的,它来自与 MVC 不同的角度。 And is really essential, once we want to cross the boundaries of a controller/model/view
(template) .并且非常重要,一旦我们想要跨越
controller/model/view
(模板)的边界。
Let' start with the parameters which are passed into the link
function:让我们从传递给
link
函数的参数开始:
function link(scope, element, attrs) {
To put the link
into the context, we should mention that all directives are going through this initialization process steps: Compile , Link .为了将
link
放入上下文中,我们应该提到所有指令都经过这个初始化过程步骤: Compile , Link 。 An Extract from Brad Green and Shyam Seshadri book Angular JS :摘自Brad Green 和 Shyam Seshadri 的书 Angular JS :
Compile phase (a sister of link, let's mention it here to get a clear picture):编译阶段(链接的姐妹,这里提一下,看清楚):
In this phase, Angular walks the DOM to identify all the registered directives in the template.在这个阶段,Angular 遍历 DOM 以识别模板中所有已注册的指令。 For each directive, it then transforms the DOM based on the directive's rules (template, replace, transclude, and so on), and calls the compile function if it exists.
对于每个指令,它然后根据指令的规则(模板、替换、转换等)转换 DOM,如果存在则调用 compile 函数。 The result is a compiled template function,
结果是一个编译好的模板函数,
Link phase :链接阶段:
To make the view dynamic, Angular then runs a link function for each directive.
为了使视图动态化,Angular 会为每个指令运行一个链接函数。 The link functions typically creates listeners on the DOM or the model.
链接函数通常在 DOM 或模型上创建侦听器。 These listeners keep the view and the model in sync at all times.
这些侦听器始终保持视图和模型同步。
A nice example how to use the link
could be found here: Creating Custom Directives .可以在此处找到如何使用该
link
一个很好的示例:创建自定义指令。 See the example: Creating a Directive that Manipulates the DOM , which inserts a "date-time" into page, refreshed every second.请参阅示例:创建操作 DOM 的指令,该指令将“日期时间”插入页面,每秒刷新一次。
Just a very short snippet from that rich source above, showing the real manipulation with DOM.只是来自上面丰富资源的一个非常短的片段,显示了对 DOM 的真实操作。 There is hooked function to $timeout service, and also it is cleared in its destructor call to avoid memory leaks
$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);
});
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.