控制器可以执行指令无法执行的操作?

时间:2018-08-24 14:23:22

标签: javascript angularjs

我刚开始使用AngularJS。当我第一次开始阅读它时,从初学者教程看来,控制器是角度应用程序的基本构建块。但是,自从学习指令以来,我一直在创建自己的小Angular应用,它仅使用指令,而实际上不是单个控制器。我看不到为什么我需要控制器。

我见过的唯一一件用控制器完成的事情就是在范围内添加变量:

angular.controller("myController",
    function($scope)       
    {
        $scope.x = 5;
        $scope.y = 6;
    }
)

但是我也可以使用指令,通过使用传递给链接函数的scope参数来实现。

还有其他可以通过控制器完成的事情,而不能通过指令来完成?还是至少比控制器更容易执行指令?

例如,如果我只需要用一些变量xy填充范围,则可以执行以下操作:

angular.directive(
    "myDirective",
    function()
    {
        return {
            link: function(scope, element, attributes)
            {
                scope.x = 5;
                scope.y = 6;
            }
        };
    }
);

1 个答案:

答案 0 :(得分:1)

您肯定可以在link回调中编写几乎所有应用程序需要的内容。请注意,我什至不称其为指令,而是说 link回调。指令是用于定义自定义HTML标记及其相关功能的东西,link回调只是其中的特定部分。

问题是,这只不过是使用jQuery或使用addEventListener将行为附加到HTML元素而已。另一方面,您可以将控制器编写为类,而不是操作scope对象的过程代码。这是我在中写的首选样式:

export default class WidgetController {
    error: string;

    static $inject = ['$state', 'FooService', 'BarService'];

    constructor(
        protected $state: angular.ui.IStateService,
        protected foo: FooService,
        protected bar: BarService
    ) {}

    get fooValue() {
        return this.foo.baz;
    }

    doSomething() {
        this.error = null;
        this.bar.getSomething().then(data => {
            if (data.error) {
                this.error = data.error;
            } else {
                this.$state.go('success');
            }
        });
    }
}

一个模板可能看起来像这样:

<h1>{{ $ctrl.fooValue }}</h1>
<button ng-click="$ctrl.doSomething()">Do!</button>
<p>{{ $ctrl.error }}</p>

可以使用ui路由器将控制器连接到模板:

import WidgetController from 'widget-controller';

module.config(['$stateProvider', ($state: angular.ui.IStateProvider) => {
    $state.state('widget', {
        controller: WidgetController,
        controllerAs: '$ctrl',
        templateUrl: '/templates/widget.html',
    });
}]);

或作为组件:

module.component('widget', {
    templateUrl: '/templates/widget.html',
    controller: WidgetController,
    bindings: {
        error: '@'
    }
});

或者使用ng-controller或其他多种方式。

它为您提供了更大的灵活性。由于它只是一个常规类,它使您可以轻松地测试隔离控制器。它允许您为不同的模板重用控制器,并为不同的控制器重用同一模板(是的,这实际上非常有用)。它使IMO更具可读性,更易于理解。专门在模板中使用$ctrl.可以防止您构建过于相互依赖的嵌套作用域,并显式绑定模板以仅使用其控制器,而不使用某些隐式作用域。

做事的方法有很多,但是随着时间的推移,我发现的一件事是处理scope对象既冗长又令人讨厌,并且很容易导致产生意大利面条式代码。因此,远离它,您很快就会将控制器作为对象。