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

在文件中,他们解释说:

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

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

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

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


当前回答

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

控制器——创建一个控制器,它发布一个API用于跨指令通信。指令对指令通信就是一个很好的例子 Link -以编程方式修改生成的DOM元素实例,添加事件侦听器,并设置数据绑定。 Compile -通过编程方式修改DOM模板,以获得跨指令副本的特性,就像在ng-repeat中使用的那样。编译函数还可以返回链接函数来修改生成的元素实例。

其他回答

编译:

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

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

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

连接阶段:

The linking phase is where you attach the data ( $scope ) to the linking function and it should return you the linked html. Since the directive also specifies where this html goes or what it changes, it is already good to go. This is the function where you want to make changes to the linked html, i.e the html that already has the data attached to it. In angular if you write code in the linking function its generally the post-link function (by default). It is kind of a callback that gets called after the linking function has linked the data with the template.

控制器:

The controller is a place where you put in some directive specific logic. This logic can go into the linking function as well, but then you would have to put that logic on the scope to make it "shareable". The problem with that is that you would then be corrupting the scope with your directives stuff which is not really something that is expected. So what is the alternative if two Directives want to talk to each other / co-operate with each other? Ofcourse you could put all that logic into a service and then make both these directives depend on that service but that just brings in one more dependency. The alternative is to provide a Controller for this scope ( usually isolate scope ? ) and then this controller is injected into another directive when that directive "requires" the other one. See tabs and panes on the first page of angularjs.org for an example.

另外,使用控制器函数和链接函数(因为它们都可以访问作用域、元素和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中使用的那样。编译函数还可以返回链接函数来修改生成的元素实例。

这是理解指令阶段的一个很好的示例 http://codepen.io/anon/pen/oXMdBQ?editors=101

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));
                }
            };
        }
    };
});

html

<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>

编译:当我们需要修改指令模板时使用,比如添加新表达式,在该指令内追加另一个指令 Controller:当我们需要共享/重用$scope数据时使用 link:这是一个函数,当我们需要附加事件处理程序或操作DOM时使用。