首页 > 解决方案 > 控制器能做哪些指令不能做的事情?

问题描述

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

我见过的唯一使用控制器完成的事情就是将变量添加到范围:

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

但是我也可以使用指令来做到这一点,方法是使用scope传递给链接函数的参数。

有没有其他可以用控制器完成的事情,而不能用指令完成?或者至少是控制器比指令更容易做的事情?

例如,如果我只需要用一些变量xan填充范围y,我可以这样做:

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

标签: javascriptangularjs

解决方案


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-router 附加到模板:

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对象既冗长又烦人,并且很容易导致意大利面条式代码。因此,远离这一点,您很快就会将控制器作为对象。


推荐阅读