Улучшить эту документациюКонтроллеры
В Angular контроллер определяется функцией-конструктором JavaScript, которая используется для расширения области видимости Angular.
Когда контроллер прикрепляется к DOM с помощью директивы ng-controller, Angular создаст новый объект контроллера, используя указанную функцию-конструктор контроллера. Будет создана новая дочерняя область видимости, доступная в качестве параметра для инъекции в конструктор контроллера как $scope.
Если контроллер был прикреплён с помощью controller as синтаксиса, то экземпляр контроллера будет назначен в свойство новой области видимости.
Используйте контроллеры для:
- Настройки начального состояния объекта
$scope. - Добавления поведения к объекту
$scope.
Не используйте контроллеры для:
- Изменения DOM — контроллеры должны содержать только бизнес-логику. Включение любой презентационной логики в контроллеры значительно снижает его тестируемость. Angular предоставляет связывание данных для большинства случаев и директивы для инкапсуляции ручного управления DOM.
- Форматирования ввода — используйте элементы управления формами Angular вместо этого.
- Фильтрации вывода — используйте фильтры Angular вместо этого.
- Обмена кодом или состоянием между контроллерами — используйте сервисы Angular вместо этого.
- Управления жизненным циклом других компонентов (например, для создания экземпляров сервисов).
Настройка начального состояния объекта $scope
Обычно при создании приложения вам необходимо настроить начальное состояние Angular $scope. Начальное состояние области видимости устанавливается путём добавления свойств к объекту $scope. Свойства содержат модель представления (модель, которая будет отображаться в представлении). Все свойства $scope будут доступны шаблону в той точке DOM, где зарегистрирован контроллер.
Следующий пример демонстрирует создание GreetingController, который добавляет свойство greeting со строковым значением 'Hola!' к объекту $scope:
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
Мы создаём модуль Angular, myApp, для нашего приложения. Затем мы добавляем функцию-конструктор контроллера в модуль с помощью метода .controller(). Это позволяет убрать функцию-конструктор контроллера из глобальной области видимости.
$scope, предоставляемого Angular. Подробнее см. руководство по инъекции зависимостей. Мы прикрепляем наш контроллер к DOM с помощью директивы ng-controller. Свойство greeting теперь может быть связано с шаблоном:
<div ng-controller="GreetingController">
{{ greeting }}
</div>
Добавление поведения к объекту области видимости
Для реакции на события или выполнения вычислений в представлении мы должны предоставить поведение области видимости. Добавляем поведение к области видимости, прикрепляя методы к объекту $scope. Эти методы затем доступны для вызова из шаблона/представления.
Следующий пример использует контроллер для добавления метода в область видимости, который удваивает число:
var myApp = angular.module('myApp',[]);
myApp.controller('DoubleController', ['$scope', function($scope) {
$scope.double = function(value) { return value * 2; };
}]);
После того, как контроллер был прикреплен к DOM, метод double можно вызвать в выражении Angular в шаблоне:
<div ng-controller="DoubleController">
Two times <input ng-model="num"> equals {{ double(num) }}
</div>
Как обсуждалось в разделе Концепции данного руководства, любые объекты (или примитивы), назначенные области видимости, становятся свойствами модели. Любые методы, назначенные области видимости, доступны в шаблоне/представлении и могут быть вызваны с помощью выражений Angular и ng обработчиками событий (например, ngClick).
Использование контроллеров правильно
Как правило, контроллер не должен пытаться делать слишком много. Он должен содержать только бизнес-логику, необходимую для одного представления.
Наиболее распространённый способ сохранения компактности контроллеров заключается в инкапсуляции работы, которая не относится к контроллерам, в сервисы, а затем использовании этих сервисов в контроллерах с помощью инъекции зависимостей. Это обсуждается в разделах инъекции зависимостей и сервисов данного руководства.
Связывание контроллеров с объектами области видимости Angular
Вы можете неявно связать контроллеры с объектами области видимости с помощью директивы ngController или сервиса $route.
Чтобы далее проиллюстрировать, как работают компоненты контроллеров в Angular, давайте создадим небольшое приложение с такими компонентами:
- Шаблон шаблона с двумя кнопками и простым сообщением
- Модель, состоящая из строки с именем
spice - Контроллер с двумя функциями, которые устанавливают значение
spice
Сообщение в нашем шаблоне содержит привязку к модели spice, которая по умолчанию устанавливается в строку "very". В зависимости от нажатой кнопки, модель spice устанавливается в chili или jalapeño, и сообщение автоматически обновляется за счёт привязки данных.
Следует обратить внимание на следующие моменты в приведённом примере:
- Директива
ng-controllerиспользуется для (неявного) создания области видимости для нашего шаблона, и область видимости расширяется (управляется) контроллеромSpicyController. -
SpicyController— это просто обычная функция JavaScript. В качестве (необязательной) соглашения об именах имя начинается с заглавной буквы и заканчивается словом «Контроллер». - Назначение свойства объекту
$scopeсоздаёт или обновляет модель. - Методы контроллера могут создаваться путём прямого назначения в область видимости (см. метод
chiliSpicy) - Методы и свойства контроллера доступны в шаблоне (как для элемента
<div>, так и для его дочерних элементов).
Методы контроллера также могут принимать аргументы, как показано в следующем варианте предыдущего примера.
Обратите внимание, что контроллер SpicyController теперь определяет только один метод, называемый spicy, который принимает один аргумент, называемый spice. Шаблон затем обращается к этому методу контроллера и передает строковую константу 'chili' в привязке для первой кнопки и свойство модели customSpice (привязанное к текстовому полю) во второй кнопке.
Контроллеры часто прикрепляются на разных уровнях иерархии DOM. Поскольку директива ng-controller создаёт новую дочернюю область видимости, у нас появляется иерархия областей видимости, которые наследуют друг от друга. Область видимости $scope, которую получает каждый контроллер, имеет доступ к свойствам и методам, определённым контроллерами на более высоких уровнях иерархии. Подробнее об наследовании областей видимости см. Понимание областей видимости.
Обратите внимание, как мы вложили три директивы ng-controller в наш шаблон. Это приведёт к созданию четырёх областей видимости для нашего представления:
- Корневая область видимости
- Область видимости
MainController, которая содержит свойстваtimeOfDayиname - Область видимости
ChildController, которая наследует свойствоtimeOfDay, но переопределяет (скрывает) свойствоnameот предыдущей - Область видимости
GrandChildController, которая переопределяет (скрывает) и свойствоtimeOfDay, определённое вMainController, и свойствоname, определённое вChildController
Наследование работает с методами так же, как и со свойствами. Поэтому во всех наших предыдущих примерах все свойства могли быть заменены методами, которые возвращают строковые значения.
Тестирование контроллеров
Хотя существует много способов тестирования контроллера, одно из лучших соглашений, показанное ниже, включает инъекцию $rootScope и $controller:
Определение контроллера:
var myApp = angular.module('myApp',[]);
myApp.controller('MyController', function($scope) {
$scope.spices = [{"name":"pasilla", "spiciness":"mild"},
{"name":"jalapeno", "spiciness":"hot hot hot!"},
{"name":"habanero", "spiciness":"LAVA HOT!!"}];
$scope.spice = "habanero";
});
Тест контроллера:
describe('myController function', function() {
describe('myController', function() {
var $scope;
beforeEach(module('myApp'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
$controller('MyController', {$scope: $scope});
}));
it('should create "spices" model with 3 spices', function() {
expect($scope.spices.length).toBe(3);
});
it('should set the default value of spice', function() {
expect($scope.spice).toBe('habanero');
});
});
});
Если вам нужно протестировать вложенный контроллер, вы должны создать такую же иерархию областей видимости в своём тесте, которая существует в DOM:
describe('state', function() {
var mainScope, childScope, grandChildScope;
beforeEach(module('myApp'));
beforeEach(inject(function($rootScope, $controller) {
mainScope = $rootScope.$new();
$controller('MainController', {$scope: mainScope});
childScope = mainScope.$new();
$controller('ChildController', {$scope: childScope});
grandChildScope = childScope.$new();
$controller('GrandChildController', {$scope: grandChildScope});
}));
it('should have over and selected', function() {
expect(mainScope.timeOfDay).toBe('morning');
expect(mainScope.name).toBe('Nikki');
expect(childScope.timeOfDay).toBe('morning');
expect(childScope.name).toBe('Mattie');
expect(grandChildScope.timeOfDay).toBe('evening');
expect(grandChildScope.name).toBe('Gingerbread Baby');
});
});
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.3.20/docs/guide/controller