Улучшить эту документациюМодули
Что такое модуль?
Модуль можно представить как контейнер для различных частей вашего приложения – контроллеров, сервисов, фильтров, директив и т.д.
Почему?
Большинство приложений имеют главный метод, который инициализирует и связывает различные части приложения.
Приложения AngularJS не имеют главного метода. Вместо этого модули декларативно указывают, как приложение должно быть запущено. Такой подход имеет несколько преимуществ:
- Декларативный процесс легче понять.
- Вы можете упаковать код в виде повторно используемых модулей.
- Модули могут загружаться в любом порядке (или даже параллельно), потому что модули откладывают выполнение.
- Тесты модулей (unit tests) должны загружать только соответствующие модули, что обеспечивает их быстродействие.
- Тесты на конец-в-конец (end-to-end tests) могут использовать модули для переопределения конфигурации.
Основы
У меня мало времени. Как создать работающий модуль "Привет, мир"?
Важные моменты:
- API модуля
- Ссылка на
myAppмодуль в<div ng-app="myApp">. Это то, что запускает приложение с использованием вашего модуля. - Пустой массив в
angular.module('myApp', []). Этот массив представляет список модулей, от которыхmyAppзависит.
Рекомендуемая настройка
Хотя приведенный выше пример прост, он не масштабируется для больших приложений. Вместо этого рекомендуется разбить ваше приложение на несколько модулей, как показано ниже:
- Модуль для каждой функции
- Модуль для каждого повторно используемого компонента (особенно директив и фильтров)
- И модуль уровня приложения, который зависит от вышеперечисленных модулей и содержит код инициализации.
Вы можете найти руководство по стилю сообщества здесь, чтобы помочь вам при росте приложения.
Вышеупомянутые рекомендации носят рекомендательный характер. Приспосабливайте их к вашим потребностям.
Загрузка модулей
Модуль — это набор поставщиков, сервисов, директив и, необязательно, блоков конфигурации и выполнения, которые применяются к приложению во время процесса запуска.
API модуля описывает все доступные методы и способы их использования.
См. Использование инъекции зависимостей, чтобы узнать, какие зависимости можно вводить в каждом методе.
Зависимости и порядок выполнения
Модули могут перечислять другие модули в качестве своих зависимостей. Зависимость от модуля подразумевает, что требуемый модуль будет загружен до загрузки модуля, который его требует.
В рамках одного модуля порядок выполнения следующий:
-
Выполняются функции provider, поэтому они и определяемые ими сервисы могут быть доступны для $injector.
-
После этого выполняются блоки конфигурации (config функции). Это означает, что блоки конфигурации необходимых модулей выполняются до блоков конфигурации модулей, которые их требуют.
Это продолжается до тех пор, пока все зависимости модулей не будут разрешены.
Затем блоки run, собранные из каждого модуля, выполняются в порядке зависимости.
Примечание: каждый модуль загружается только один раз, даже если его требуют несколько других модулей. Примечание: функция-фабрика для «значений» и «сервисов» вызывается лениво, когда значение/сервис вводится впервые.
Регистрация в блоке конфигурации
Хотя рекомендуется регистрировать инъектируемые объекты непосредственно с помощью API модуля, также можно регистрировать сервисы, директивы и т. д., введя $provide или отдельных поставщиков сервисов в функцию конфигурации:
angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);
// is same as
angular.module('myModule', []).
config(function($provide, $compileProvider, $filterProvider) {
$provide.value('a', 123);
$provide.factory('a', function() { return 123; });
$compileProvider.directive('directiveName', ...);
$filterProvider.register('filterName', ...);
});
Блоки run
Блоки run — это ближайший аналог главного метода в AngularJS. Блок run — это код, который требуется для запуска приложения. Он выполняется после конфигурирования всех сервисов и создания инжектора. Блоки run обычно содержат код, который трудно протестировать, и поэтому должны объявляться в изолированных модулях, чтобы их можно было игнорировать в модульных тестах.
Асинхронная загрузка
Модули являются способом управления конфигурацией $injector и не связаны с загрузкой скриптов в виртуальную машину. Существуют проекты, которые занимаются загрузкой скриптов, которые могут использоваться с AngularJS. Поскольку модули ничего не делают во время загрузки, их можно загрузить в виртуальную машину в любом порядке, и, следовательно, загрузчики скриптов могут воспользоваться этой особенностью и распараллелить процесс загрузки.
Создание против получения
Будьте осторожны, что использование angular.module('myModule', []) создаст модуль myModule и перезапишет любой существующий модуль с именем myModule. Используйте angular.module('myModule') для получения существующего модуля.
var myModule = angular.module('myModule', []);
// add some directives and services
myModule.service('myService', ...);
myModule.directive('myDirective', ...);
// overwrites both myService and myDirective by creating a new module
var myModule = angular.module('myModule', []);
// throws an error because myOtherModule has yet to be defined
var myModule = angular.module('myOtherModule');
Модульное тестирование
Модульный тест — это способ создания подмножества приложения для применения к нему стимулов. Небольшие структурированные модули помогают поддерживать модульные тесты лаконичными и целенаправленными.
Во всех этих примерах мы будем предполагать следующее определение модуля:
angular.module('greetMod', []).
factory('alert', function($window) {
return function(text) {
$window.alert(text);
}
}).
value('salutation', 'Hello').
factory('greet', function(alert, salutation) {
return function(name) {
alert(salutation + ' ' + name + '!');
}
});
Давайте напишем некоторые тесты, чтобы показать, как переопределить конфигурацию в тестах.
describe('myApp', function() {
// load application module (`greetMod`) then load a special
// test module which overrides `$window` with a mock version,
// so that calling `window.alert()` will not block the test
// runner with a real alert box.
beforeEach(module('greetMod', function($provide) {
$provide.value('$window', {
alert: jasmine.createSpy('alert')
});
}));
// inject() will create the injector and inject the `greet` and
// `$window` into the tests.
it('should alert on $window', inject(function(greet, $window) {
greet('World');
expect($window.alert).toHaveBeenCalledWith('Hello World!');
}));
// this is another way of overriding configuration in the
// tests using inline `module` and `inject` methods.
it('should alert using the alert service', function() {
var alertSpy = jasmine.createSpy('alert');
module(function($provide) {
$provide.value('alert', alertSpy);
});
inject(function(greet) {
greet('World');
expect(alertSpy).toHaveBeenCalledWith('Hello World!');
});
});
});
© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.7.8/docs/guide/module