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

在文件中,他们解释说:

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

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

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

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


当前回答

指令允许您以声明式的方式扩展HTML词汇表,以构建web组件。ng-app属性是一个指令,ng-controller和所有ng前缀的属性也是一个指令。指令可以是属性、标签,甚至是类名、注释。

指令如何生成(编译和实例化)

Compile:我们将使用Compile函数在DOM呈现之前操作它,并返回一个链接函数(该函数将为我们处理链接)。这也是放置任何需要与该指令的所有实例共享的方法的地方。

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

如果在compile()函数中设置,它们只会被设置一次(这通常是你想要的)。如果在link()函数中设置,则在HTML元素绑定到 对象。

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

     }
   };
});

编译函数返回前后链接函数。在pre - link函数中,我们有实例模板,也有来自控制器的作用域,但模板没有绑定到作用域,仍然没有透光的内容。

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

其他回答

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

指令允许您以声明式的方式扩展HTML词汇表,以构建web组件。ng-app属性是一个指令,ng-controller和所有ng前缀的属性也是一个指令。指令可以是属性、标签,甚至是类名、注释。

指令如何生成(编译和实例化)

Compile:我们将使用Compile函数在DOM呈现之前操作它,并返回一个链接函数(该函数将为我们处理链接)。这也是放置任何需要与该指令的所有实例共享的方法的地方。

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

如果在compile()函数中设置,它们只会被设置一次(这通常是你想要的)。如果在link()函数中设置,则在HTML元素绑定到 对象。

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

     }
   };
});

编译函数返回前后链接函数。在pre - link函数中,我们有实例模板,也有来自控制器的作用域,但模板没有绑定到作用域,仍然没有透光的内容。

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

这是理解指令阶段的一个很好的示例 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>

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

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

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

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

vs.

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