Оптимальные методы AngularJS для объявления модулей?
У меня есть куча модулей Angular, объявленных в моем приложении. Сначала я начал объявлять их с помощью синтаксиса "цепочка":
angular.module('mymodule', [])
.controller('myctrl', ['dep1', function(dep1){ ... }])
.service('myservice', ['dep2', function(dep2){ ... }])
... // more here
Но я решил, что читать это было не так просто, поэтому я начал объявлять их с помощью модульной переменной следующим образом:
var mod = angular.module('mymodule', []);
mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
mod.service('myservice', ['dep2', function(dep2){ ... }]);
...
Второй синтаксис кажется мне более читаемым, но моя единственная жалоба заключается в том, что этот синтаксис оставляет переменную mod
в глобальной области. Если у меня когда-нибудь будет другая переменная с именем mod
, она будет переопределена следующей следующей (и другими проблемами, связанными с глобальными переменными).
Итак, мой вопрос: это лучший способ? Или было бы лучше сделать что-то подобное?:
(function(){
var mod = angular.module('mymod', []);
mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
mod.service('myservice', ['dep2', function(dep2){ ... }]);
...
})();
Или это даже достаточно важно, чтобы заботиться? Просто любопытно узнать, что такое "лучшие практики" для декларации модуля. Спасибо заранее.
Ответы
Ответ 1
Лучший способ объявить модуль
Поскольку angular находится в самой глобальной области и модули сохраняются в своей переменной, вы можете получать доступ к модулям через angular.module('mymod')
:
// one file
// NOTE: the immediately invoked function expression
// is used to exemplify different files and is not required
(function(){
// declaring the module in one file / anonymous function
// (only pass a second parameter THIS ONE TIME as a redecleration creates bugs
// which are very hard to dedect)
angular.module('mymod', []);
})();
// another file and/or another anonymous function
(function(){
// using the function form of use-strict...
"use strict";
// accessing the module in another.
// this can be done by calling angular.module without the []-brackets
angular.module('mymod')
.controller('myctrl', ['dep1', function(dep1){
//..
}])
// appending another service/controller/filter etc to the same module-call inside the same file
.service('myservice', ['dep2', function(dep2){
//...
}]);
// you can of course use angular.module('mymod') here as well
angular.module('mymod').controller('anothermyctrl', ['dep1', function(dep1){
//..
}])
})();
Других глобальных переменных не требуется.
Конечно, все зависит от предпочтений, но я думаю, что это своего рода лучшая практика, поскольку
- вам не нужно загрязнять глобальную область.
- вы можете получать доступ к своим модулям повсюду и сортировать их и их функции в разные файлы по своему усмотрению.
- вы можете использовать функциональную форму "use strict";
- порядок загрузки файлов не имеет значения
Параметры для сортировки ваших модулей и файлов
Этот способ декларирования и доступа к модулям делает вас очень гибким. Вы можете сортировать модули с помощью функционального типа (как описано в другом ответе) или по маршруту, например:
/******** sorting by route **********/
angular.module('home')...
angular.module('another-route')...
angular.module('shared')...
Как вы его сортируете, в конце концов, это вопрос личного вкуса, масштаб и тип проекта. Мне лично нравится группировать все файлы модуля внутри одной и той же папки (упорядоченные в подпапки директив, контроллеров, сервисов и фильтров), включая все разные тестовые файлы, поскольку это делает ваши модули более многоразовыми. Таким образом, в проектах среднего размера я получаю базовый модуль, который включает в себя все основные маршруты и их контроллеры, службы, директивы и более или менее сложные подмодули, когда я думаю, что они могут быть полезны и для других проектов, например
/******** modularizing feature-sets **********/
/controllers
/directives
/filters
/services
/my-map-sub-module
/my-map-sub-module/controllers
/my-map-sub-module/services
app.js
...
angular.module('app', [
'app.directives',
'app.filters',
'app.controllers',
'app.services',
'myMapSubModule'
]);
angular.module('myMapSubModule',[
'myMapSubModule.controllers',
'myMapSubModule.services',
// only if they are specific to the module
'myMapSubModule.directives',
'myMapSubModule.filters'
]);
Для очень больших проектов я иногда группирую модули по маршрутам, как описано выше, или некоторыми выбранными основными маршрутами или даже комбинацией маршрутов и некоторых выбранных компонентов, но это действительно зависит.
EDIT:
Просто потому, что это связано, и я снова столкнулся с этим: Позаботьтесь о том, чтобы создать модуль только один раз (добавив второй параметр в функцию angular.module-function). Это испортит ваше приложение и может быть очень сложно обнаружить.
2015 EDIT для модулей сортировки:
Спустя полтора года из angular -experience позже я могу добавить, что преимущества использования именованных модулей в вашем приложении несколько ограничены, поскольку AMD по-прежнему не очень хорошо работает с angular, а службы, директивы и фильтры глобально доступный внутри контекста angular в любом случае (как показано здесь). По-прежнему существует семантическое и структурное преимущество, хотя и может быть полезно включить/исключить модуль с одной строкой кода, прокомментированной или отсутствующей.
Он также почти никогда не имеет смысла разделять подмодули по типу (например, "myMapSubModule.controllers" ), поскольку они обычно зависят друг от друга.
Ответ 2
Мне нравится angular-styleguide от Johnpapa, и вот некоторые правила, связанные с этим вопросом:
Правило: Именованные и анонимные функции
Избегайте использования анонимных функций:
// dashboard.js
angular
.module('app')
.controller('Dashboard', function() { })
Вместо этого используйте именованные функции:
// dashboard.js
angular
.module('app')
.controller('Dashboard', Dashboard);
function Dashboard() { }
Как говорит автор: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code.
Правило: укажите 1 компонент на файл.
Избегайте нескольких компонентов в одном файле:
angular
.module('app', ['ngRoute'])
.controller('SomeController', SomeController)
.factory('someFactory', someFactory);
function SomeController() { }
function someFactory() { }
Intead, используйте один файл для определения модуля:
// app.module.js
angular
.module('app', ['ngRoute']);
один файл просто использует модуль для определения компонента
// someController.js
angular
.module('app')
.controller('SomeController', SomeController);
function SomeController() { }
и еще один файл для определения другого компонента
// someFactory.js
angular
.module('app')
.factory('someFactory', someFactory);
function someFactory() { }
Конечно, существует множество других правил для модулей, контроллеров и сервисов, которые весьма полезны и заслуживают внимания.
И благодаря комментарию ya_dimon, вышеуказанный код должен быть завернут в IIFE, например:
(function (window, angular) {
angular.module('app')
.controller('Dashboard', function () { });
})(window, window.angular);
Ответ 3
У меня недавно была эта головоломка. Я начал работать так же, как вы, используя цепочку синтаксиса, но в конечном итоге он становится громоздким с крупными проектами. Обычно я создавал модуль контроллеров, модуль служб и т.д. В отдельных файлах и вставлял их в свой основной прикладной модуль, находящийся в другом файле. Например:
// My Controllers File
angular.module('my-controllers',[])
.controller('oneCtrl',[...])
.controller('twoCtrl',[...]);
// My Services File
angular.module('my-services',[])
.factory('oneSrc',[...])
.facotry('twoSrc',[...]);
// My Directives File
angular.module('my-directives',[])
.directive('oneDrct',[...])
.directive('twoDrct',[...]);
// My Main Application File
angular.module('my-app',['my-controllers','my-services','my-directives',...]);
Но каждый из этих файлов приближался к большому по мере роста проекта. Поэтому я решил разбить их на отдельные файлы на основе каждого контроллера или службы. Я обнаружил, что использование angular.module('mod-name').
без массива инъекций - вот что вам нужно для этого. Объявление глобальной переменной в одном файле и ожидание ее доступности в другом просто не работает или может иметь неожиданные результаты.
Короче, мое приложение выглядело примерно так:
// Main Controller File
angular.module('my-controllers',[]);
// Controller One File
angular.module('my-controllers').controller('oneCtrl',[...]);
//Controller Two File
angular.module('my-controllers').controller('twoCtrl',[...]);
Я сделал это и с файлом служб, не нужно менять основной файл модуля приложения, в который вы все равно будете вводить те же модули.
Ответ 4
Еще одна практика заключается в том, чтобы заполнять контроллеры, директивы и т.д. в своих собственных модулях и вставлять эти модули в ваш "основной":
angular.module('app.controllers', [])
.controller('controller1', ['$scope', function (scope) {
scope.name = "USER!";
}]);
angular.module('app.directives', [])
.directive('myDirective', [function () {
return {
restrict: 'A',
template: '<div>my directive!</div>'
}
}]);
angular.module('app', [
'app.controllers',
'app.directives'
]);
В глобальной области ничего не осталось.
http://plnkr.co/edit/EtzzPRyxWT1MkhK7KcLo?p=preview
Ответ 5
Мне нравится делиться моими файлами и моими модулями.
Что-то вроде этого:
app.js
var myApp = angular.module('myApp', ['myApp.controllers', 'myApp.directives', 'myApp.services']);
myApp.config(['$routeProvider', function($routeProvider) {
/* routes configs */
$routeProvider.when(/*...*/);
}]);
directives.js
var myDirectives = angular.module('myApp.directives', []);
myDirectives.directive( /* ... */ );
service.js
var myServices = angular.module('myApp.services', []);
myServices.factory( /* ... */ );
Я не большой поклонник "цепного стиля", поэтому я предпочитаю всегда записывать свою переменную.
Ответ 6
Для меня цепочка является самым компактным способом:
angular.module("mod1",["mod1.submod1"])
.value("myValues", {
...
})
.factory("myFactory", function(myValues){
...
})
.controller("MainCtrl", function($scope){
// when using "Ctrl as" syntax
var MC = this;
MC.data = ...;
})
;
Таким образом, я могу легко перемещать компоненты между модулями, никогда не нужно дважды объявлять один и тот же модуль, никогда не нуждаясь в глобальных переменных.
И если файл слишком длинный, решение прост - разделите на два файла, каждый из которых объявит свой собственный модуль наверху. Для большей прозрачности я пытаюсь сохранить один уникальный модуль для каждого файла и называть его похожим на полный путь к файлу. Таким образом, мне также не нужно писать модуль без []
, который является общей точкой боли.
Ответ 7
Я предлагаю следовать Руководство по стилю Angularjs.
Они обрабатывают все понятия из соглашения об именах, модуляции вашего приложения и т.д.
Для angular 2 вы можете проверить Angular 2 Руководство по стилю