在自定义指令中,`controller`对`link`有什么功能?

时间:2015-08-19 14:48:03

标签: angularjs angularjs-directive

在试图掌握创建我自己的AngularJS指令时,我有一个例子可以完成我需要的一切,但是我意识到借用各种示例,我现在可以在两个示例中为指令创建功能控制器以及链接

似乎我可以一起摆脱控制器并将所有内容放入链接,或者我可以使用控制器做些什么我可以& #39; t做链接?

http://jsfiddle.net/edwardtanguay/gxr49h96/6

.directive('itemMenu', function () {

    var controller = function ($scope) {
        var vm = this;
        vm.addItem = function () {
            $scope.add();
            vm.items.push({
                'kind': 'undefined',
                    'firstName': 'Joe',
                    'lastName': 'Newton',
                    'age': Math.floor(Math.random() * 60) + 20
            });
        };

        // DOES THE SAME AS THE FUNCTION DEFINED BELOW IN LINK        
        //        $scope.convertToInternal = function(item) {
        //            item.internalcode = 'X0000';
        //            item.kind = 'internal';
        //        };        
    };

    return {
        restrict: 'A',
        scope: {
            item: '=',
            add: '&'
        },
        controller: controller,
        controllerAs: 'vm',
        bindToController: true,
        template: '<div ng-include="getTemplateUrl()"></div>',
        link: function (scope, element, attrs) {
            scope.getTemplateUrl = function () {
                switch (scope.item.kind) {
                    case 'external':
                        return 'itemMenuTemplateExternal';
                    case 'internal':
                        return 'itemMenuTemplateInternal';
                    default:
                        return 'itemMenuTemplateUndefined';
                }
            };

            scope.convertToInternal = function(item) {
                item.internalcode = 'X0000';
                item.kind = 'internal';
            };
        },
    };

})

1 个答案:

答案 0 :(得分:2)

您可能会发现很多关于控制器与链接的含糊不清的咆哮,其中大多数都包含来自$compile服务文档的信息。

直接回答问题,

  • 来自其他模块/文件的控制器可以通过Angular DI与controller: 'Controller'

  • 插入指令
  • controller可以注入依赖项,而link具有固定参数列表,并通过指令的依赖项获取

  • controllerlink之前启动,因此它可以在某些条件下准备链接或重新编译元素的范围尽快

  • 控制器功能具有this,其代码外观符合其他类似OOP的ES5代码,并且这些方法可以在其他代码部分之间轻松传输,例如: service服务或第三方代码

  • 因此,控制器适合定义为ES2015TS类。

  • 指令的控制器可以通过子指令require d,并提供这两者之间方便的单向交互

  • controller使用bindToController: true + controllerAs: 'vm'并实现$scope.vm配方(特别有助于对抗JS原型继承),同时保留this语法

  • bindToController object value为继承的scope: true范围提供属性绑定,不再提供$attr.$observe

  • bindToController对象值为隔离范围提供了进一步的粒度。如果某些属性应绑定到控制器并使用require访问,则可以立即执行

哪个代码转到controller哪个转到link是一个更微妙的问题。

传统上使用Angular控制器作为视图模型,如MVVM(因此controllerAs: 'vm'约定),因此如果控制器有作业(即将服务绑定到作用域值或设置)范围观察者)将它交给他们,其余的留给link

由于$attrs$element$transclude本地依赖关系应该明确地注入控制器,因此可以认为它是跳过它们的标志($scope也应注入对于$scope.$方法,但我们将忽略这一事实。)

应该通过link而不是controller来完成这项工作的一些非宗教问题。 require d控制器在控制器本身不可用,因此这种指令交互发生在link中。由于controller在比link更早的编译阶段启动,绑定的属性值将不会被插值,因此依赖于这些范围值的代码将转到link。这同样适用于其他与DOM相关的代码,它会转到link for a reason

这主要是正确的代码风格而非真正的必要性。从示例中的代码开始,所有scope内容都是控制器友好的,我认为link根本不应该存在。