链接vs编译vs控制器

创建指令时,可以将代码放入编译器、链接函数或控制器中。

在文件中,他们解释说:

  • 编译和链接函数用于angular的不同阶段 李周期< / >
  • 控制器在指令之间共享

然而,对我来说,不清楚哪种代码应该放在哪里。

例如:我可以在compile中创建函数并将它们附加到link中的作用域,还是只将函数附加到控制器中的作用域?

如果每个指令都有自己的控制器,那么指令之间如何共享控制器?控制器是真正共享的还是仅仅是作用域属性?

241878 次浏览

# EYZ0

这是Angular实际编译指令的阶段。对于每个给定指令的引用,这个编译函数只被调用一次。例如,假设您正在使用ng-repeat指令。Ng-repeat将必须查找它所附加的元素,提取它所附加的HTML片段并创建一个模板函数。

如果你使用了HandleBars,下划线模板或类似的东西,这就像编译他们的模板来提取模板函数。向这个模板函数传递数据,该函数的返回值是数据在正确位置的html。

编译阶段是Angular中返回模板函数的步骤。这个模板函数在angular中被称为链接函数。

# EYZ0

链接阶段是将数据($scope)附加到链接函数,它将返回已链接的html。由于该指令还指定了这个html的位置或它要更改的内容,所以它已经很好了。这是你想要对链接的html进行更改的函数,即已经有数据附加到它的html。在angular中,如果你在链接函数中写代码,它通常是post-link函数(默认)。它是一种回调,在链接函数将数据链接到模板之后调用。

控制器:

控制器是你放入一些指令特定逻辑的地方。这个逻辑也可以进入链接函数,但是你必须把这个逻辑放到作用域上,使它“可共享”。这样做的问题是,你会用你的指令破坏作用域,这并不是你所期望的。 那么,如果两个指令想要彼此对话/合作,有什么替代方案呢?当然,你可以把所有的逻辑放到一个服务中,然后让这两个指令都依赖于那个服务,但这只会带来更多的依赖。另一种方法是为这个作用域提供一个Controller(通常是隔离作用域?)然后当另一个指令“需要”另一个指令时,这个控制器被注入到另一个指令中。参见angularjs.org首页的标签和窗格。< / p >

另外,使用控制器函数和链接函数(因为它们都可以访问作用域、元素和attrs)的一个很好的理由是,您可以将任何可用的服务或依赖项传递到控制器中(并且以任何顺序),而使用链接函数则不能这样做。注意不同的特征:

controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...

vs。

link: function(scope, element, attrs) {... //no services allowed

我还想补充谷歌团队的O'Reily AngularJS书中所说的话:

控制器——创建一个控制器,它发布一个API用于跨指令通信。指令对指令通信就是一个很好的例子

Link -以编程方式修改生成的DOM元素实例,添加事件侦听器,并设置数据绑定。

Compile -通过编程方式修改DOM模板,以获得跨指令副本的特性,就像在ng-repeat中使用的那样。编译函数还可以返回链接函数来修改生成的元素实例。

这是理解指令阶段的一个很好的例子 # EYZ0 < / p >

var app = angular.module('myapp', [])


app.directive('slngStylePrelink', function() {
return {
scope: {
drctvName: '@'
},
controller: function($scope) {
console.log('controller for ', $scope.drctvName);
},
compile: function(element, attr) {
console.log("compile for ", attr.name)
return {
post: function($scope, element, attr) {
console.log('post link for ', attr.name)
},
pre: function($scope, element, attr) {
$scope.element = element;
console.log('pre link for ', attr.name)
// from angular.js 1.4.1
function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) {
element.css(style, '');
});
}
if (newStyles) element.css(newStyles);
}


$scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);


// Run immediately, because the watcher's first run is async
ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
}
};
}
};
});

超文本标记语言

<body ng-app="myapp">
<div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
<div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
</div>
</div>
</body>

directive允许您以声明式的方式扩展HTML词汇表,以构建web组件。ng-app属性是一个指令,ng-controller和所有的ng- prefixed attributes也是一个指令。指令可以是attributestags,甚至class namescomments

指令是如何诞生的(compilationinstantiation)

我们将使用compile函数在DOM渲染之前将manipulate和返回link函数(将为我们处理链接)。这也是放置任何需要与该指令的所有instances共享的方法的地方。

我们将使用link函数在特定的DOM元素(从模板克隆)上注册所有侦听器,并设置到页面的绑定。

如果在compile()函数中设置,它们只会被设置一次(这通常是你想要的)。如果在link()函数中设置,则在HTML元素绑定到中的数据时设置 < / p > < /代码>对象。
<div ng-repeat="i in [0,1,2]">
<simple>
<div>Inner content</div>
</simple>
</div>


app.directive("simple", function(){
return {
restrict: "EA",
transclude:true,
template:"<div>\{\{label}}<div ng-transclude></div></div>",
compile: function(element, attributes){
return {
pre: function(scope, element, attributes, controller, transcludeFn){


},
post: function(scope, element, attributes, controller, transcludeFn){


}
}
},
controller: function($scope){


}
};
});

Compile函数返回prepost链接函数。在pre link函数中,我们有实例模板和来自controller的作用域,但是模板没有绑定到作用域,仍然没有透光的内容。

Post链接函数是其中post链接是最后执行的函数。现在transclusion完成了,the template is linked to a scopeview will update with data bound values after the next digest cyclelink选项只是设置post-link函数的快捷方式。

指令控制器可以传递给另一个指令链接/编译阶段。它可以被注入到其他指令中,作为指令间通信的一种手段。

你必须指定需要的指令的名称——它应该绑定到同一个元素或它的父元素。名称可以加上前缀:

? – Will not raise any error if a mentioned directive does not exist.
^ – Will look for the directive on parent elements, if not available on the same element.

使用方括号[‘directive1′, ‘directive2′, ‘directive3′]来要求多个指令控制器。

var app = angular.module('app', []);


app.controller('MainCtrl', function($scope, $element) {
});


app.directive('parentDirective', function() {
return {
restrict: 'E',
template: '<child-directive></child-directive>',
controller: function($scope, $element){
this.variable = "Hi Vinothbabu"
}
}
});


app.directive('childDirective', function() {
return {
restrict:  'E',
template: '<h1>I am child</h1>',
replace: true,
require: '^parentDirective',
link: function($scope, $element, attr, parentDirectCtrl){
//you now have access to parentDirectCtrl.variable
}
}
});
  • 编译:当我们需要修改指令模板时使用,比如添加新表达式,在这个指令中添加另一个指令
  • 控制器:当我们需要共享/重用$scope数据时使用
  • 链接:这是一个函数,当我们需要附加事件处理程序或操作DOM时使用。