Как правильно загружать зависимости в суперкласс контроллера приложения AngularJS?

#javascript #angularjs #typescript

#javascript #angularjs #typescript

Вопрос:

Я создаю приложение AngularJS, которое предоставляет базовые функции CRUD. Это приложение создано с использованием TypeScript, чтобы использовать преимущества типов и классов. У меня есть базовый контроллер, которому требуется доступ к нескольким зависимостям AngularJS. Первоначально я вводил зависимости следующим образом

Файл: base-controller.ts

 class BaseController {
    private $location;
    private $routeParams;
    constructor($location, $routeParams) {
        /* Manually inject dependencies */
        this.$location = $injector.get('$location');
        this.$routeParams = $injector.get('$routeParams ');
    }
}
 

Файл: list-controller.ts

 class WorkRequestListController extends BaseController {
    /* Write code to override base controller or implement local methods */
}

angular.module('app.workRequests')
    .controller('WorkRequestListController', ['$location', '$routeParams',
        ($location, $routeParams) => new WorkRequestListController($location, $routeParams)
]);
 

Это решение работает, но требует, чтобы мой подкласс знал о зависимостях, требуемых моим базовым классом. Если мне когда-нибудь понадобится другая зависимость в моем базовом классе, мне придется изменить каждый подкласс и оператор, который создает экземпляр контроллера. Чтобы исправить эти проблемы, я теперь просто передаю $injector в свой базовый класс следующим образом:

Файл: base-controller.ts

 class BaseController {
    private $location;
    private $routeParams;
    constructor($injector) {
        /* Load dependencies */
        this.$location = $injector.get('$location');
        this.$routeParams = $injector.get('$routeParams');
    }
}
 

Файл: list-controller.ts

 class WorkRequestListController extends BaseController {
    /* Write code to override base controller or implement local methods */
}

angular.module('app.workRequests')
    .controller('WorkRequestListController', ['$injector',
        ($injector) => new WorkRequestListController($injector)
]);
 

Вот мой вопрос: является ли это правильным способом загрузки зависимостей в суперкласс, не заставляя подкласс или другой код знать о зависимостях?

Ответ №1:

Является ли это правильным способом загрузки зависимостей в суперкласс, не заставляя подкласс или другой код знать о зависимостях?

Это способ. Angular не рекомендует наследование в контроллерах. Он предпочитает компоновку. Общая функциональность должна быть реализована в сервисе / фабрике, которая внедряется в ваши контроллеры.

Комментарии:

1. Мы выбрали наследование для контроллеров, потому что у нас есть базовое поведение, которое мы хотим, чтобы все контроллеры реализовывали, и нам нужен простой способ переопределить или расширить функциональность в определенных контроллерах. Мы используем сервисы для переноса наших вызовов API, директив для компонентов и нескольких фильтров.

2. Здесь нет рекомендуемого шаблона. Но я сделал то же самое, что и вы, в своих проектах (для веб-сервисов)

Ответ №2:

На самом деле есть действительно простой способ реализовать базовый контроллер с помощью службы $controller . Недавно я написал об этом сообщение в блоге, вот фрагмент кода, показывающий, как это работает:

 'use strict';

angular.module('Diary')

// base controller containing common functions for add/edit controllers
.controller('Diary.BaseAddEditController',
    ['$scope', 'DiaryService',
    function ($scope, DiaryService) {
        $scope.diaryEntry = {};

        $scope.saveDiaryEntry = function () {
            DiaryService.SaveDiaryEntry($scope.diaryEntry);
        };

        // add any other shared functionality here.
    }])

.controller('Diary.AddDiaryController',
    ['$scope', '$controller',
    function ($scope, $controller) {
        // instantiate base controller
        $controller('Diary.BaseAddEditController', { $scope: $scope });
    }])

.controller('Diary.EditDiaryController',
    ['$scope', '$routeParams', 'DiaryService', '$controller',
    function ($scope, $routeParams, DiaryService, $controller) {
        // instantiate base controller
        $controller('Diary.BaseAddEditController', { $scope: $scope });

        DiaryService.GetDiaryEntry($routeParams.id).success(function (data) {
            $scope.diaryEntry = data;
        });
    }]);