papa - directivas personalizadas angularjs
¿Mejores prácticas de AngularJS para la declaración del módulo? (7)
Me encanta la angular-styleguide de estilo angular-styleguide de Johnpapa, y aquí hay algunas reglas relacionadas con esta pregunta:
Regla: Funciones anónimas vs anónimas
Evite usar funciones anónimas:
// dashboard.js
angular
.module(''app'')
.controller(''Dashboard'', function() { })
En su lugar, use funciones nombradas:
// dashboard.js
angular
.module(''app'')
.controller(''Dashboard'', Dashboard);
function Dashboard() { }
Como dice el autor: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code.
Regla: define 1 componente por archivo.
Evite múltiples componentes en un archivo:
angular
.module(''app'', [''ngRoute''])
.controller(''SomeController'', SomeController)
.factory(''someFactory'', someFactory);
function SomeController() { }
function someFactory() { }
Intead, use un archivo para definir el módulo:
// app.module.js
angular
.module(''app'', [''ngRoute'']);
un archivo solo usa el módulo para definir un componente
// someController.js
angular
.module(''app'')
.controller(''SomeController'', SomeController);
function SomeController() { }
y otro archivo para definir otro componente
// someFactory.js
angular
.module(''app'')
.factory(''someFactory'', someFactory);
function someFactory() { }
Por supuesto, hay muchas otras reglas para módulos, controladores y servicios que son bastante útiles y que vale la pena leer.
Y gracias al comentario de ya_dimon, el código anterior debe estar envuelto en IIFE, por ejemplo:
(function (window, angular) {
angular.module(''app'')
.controller(''Dashboard'', function () { });
})(window, window.angular);
Tengo un montón de módulos angulares declarados en mi aplicación. Originalmente comencé a declararlos usando la sintaxis "encadenada" de esta manera:
angular.module(''mymodule'', [])
.controller(''myctrl'', [''dep1'', function(dep1){ ... }])
.service(''myservice'', [''dep2'', function(dep2){ ... }])
... // more here
Pero decidí que no era muy fácil de leer, así que comencé a declararlos usando una variable de módulo como esta:
var mod = angular.module(''mymodule'', []);
mod.controller(''myctrl'', [''dep1'', function(dep1){ ... }]);
mod.service(''myservice'', [''dep2'', function(dep2){ ... }]);
...
La segunda sintaxis me parece mucho más legible, pero mi única queja es que esta sintaxis deja la variable mod
en el ámbito global. Si alguna vez tengo alguna otra variable llamada mod
, se invalidaría con la siguiente (y otros problemas asociados con variables globales).
Entonces mi pregunta es, ¿es esta la mejor manera? ¿O sería mejor hacer algo como esto ?:
(function(){
var mod = angular.module(''mymod'', []);
mod.controller(''myctrl'', [''dep1'', function(dep1){ ... }]);
mod.service(''myservice'', [''dep2'', function(dep2){ ... }]);
...
})();
¿O importa lo suficiente como para preocuparse? Solo curiosidad por saber cuáles son las "mejores prácticas" para la declaración del módulo. Gracias por adelantado.
Me gusta dividir mis archivos y mis módulos.
Algo como esto:
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( /* ... */ );
No soy un gran admirador del "estilo encadenado", así que prefiero escribir mi variable siempre.
Otra práctica es incluir controladores, directivas, etc. en sus propios módulos e inyectar esos módulos en su "principal":
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''
]);
No queda nada en el alcance global.
Para mí, el encadenamiento es la forma más compacta:
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 = ...;
})
;
De esta forma, puedo mover fácilmente componentes entre módulos, nunca necesito declarar el mismo módulo dos veces, nunca necesito ninguna variable global.
Y si el archivo es demasiado largo, la solución es simple: dividirlo en dos archivos, cada uno declarando su propio módulo en la parte superior. Para obtener más transparencia, intento mantener un único módulo por archivo y nombrarlo como la ruta completa del archivo. De esta forma también, nunca necesitaré escribir un módulo sin []
, que es un punto de dolor común.
Recientemente tuve este enigma también. Empecé como tú usando la sintaxis encadenada, pero a la larga se vuelve difícil de manejar con proyectos grandes. Normalmente crearía un módulo de controladores, un módulo de servicios, etc. en archivos separados y los inyectaría en mi módulo de aplicación principal que se encuentra en otro archivo. Por ejemplo:
// 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'',...]);
Pero cada uno de estos archivos se estaba haciendo cada vez más grande a medida que crecía el proyecto. Así que decidí dividirlos en archivos separados en función de cada controlador o servicio. Encontré eso usando angular.module(''mod-name'').
sin el conjunto de inyección, es lo que necesita para que esto funcione. Declarar una variable global en un archivo y esperar que esté fácilmente disponible en otro simplemente no funciona o podría tener resultados inesperados.
Así que, en resumen, mi aplicación se veía así:
// 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'',[...]);
También hice esto en el archivo de servicios, sin necesidad de cambiar el archivo del módulo de la aplicación principal, aún estarías inyectando los mismos módulos en eso.
Sugiero seguir Angularjs Style Guide .
Manejan todos los conceptos desde la convención de nombres, para modularizar su aplicación, etc.
Para angular 2, puede consultar la Guía de estilo angular 2
''La mejor'' manera de declarar un módulo
Como angular se encuentra en el alcance global en sí y los módulos se guardan en su variable, puede acceder a los módulos a través de 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){
//..
}])
})();
No se requieren otras variables globales.
Por supuesto, depende de todas las preferencias, pero creo que esta es una de las mejores prácticas, ya que
- no tienes que contaminar el alcance global
- puede acceder a sus módulos en todas partes y ordenarlos a ellos y sus funciones en diferentes archivos a voluntad
- puede usar la forma de función "use strict";
- el orden de carga de los archivos no importa tanto
Opciones para ordenar sus módulos y archivos
Esta forma de declarar y acceder a los módulos te hace muy flexible. Puede ordenar módulos a través del tipo de función (como se describe en otra respuesta) o vía ruta, por ejemplo:
/******** sorting by route **********/
angular.module(''home'')...
angular.module(''another-route'')...
angular.module(''shared'')...
La forma de ordenarlo al final es una cuestión de gusto personal y la escala y el tipo del proyecto. Personalmente, me gusta agrupar todos los archivos de un módulo dentro de la misma carpeta (ordenados en subcarpetas de directivas, controladores, servicios y filtros), incluidos todos los archivos de prueba diferentes, ya que hace que sus módulos sean más reutilizables. Por lo tanto, en proyectos medianos termino con un módulo base, que incluye todas las rutas básicas y sus controladores, servicios, directivas y submódulos más o menos complejos, cuando creo que también podrían ser útiles para otros proyectos, por ejemplo :
/******** 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''
]);
Para proyectos muy grandes, a veces termino agrupando módulos por rutas, como se describe arriba o por algunas rutas principales seleccionadas o incluso una combinación de rutas y algunos componentes seleccionados, pero realmente depende.
EDITAR: solo porque está relacionado y me encontré con eso muy recientemente: ten cuidado de crear un módulo solo una vez (agregando un segundo parámetro a la función angular.module). Esto arruinará su aplicación y puede ser muy difícil de detectar.
EDIT 2015 en los módulos de clasificación: un año y medio de experiencia angular más adelante, puedo agregar que los beneficios del uso de módulos con nombres diferentes dentro de su aplicación son algo limitados ya que AMD aún no funciona bien con Angular y servicios, directivas y filtros están globalmente disponibles dentro del contexto angular de todos modos ( como se ejemplifica aquí ). Sin embargo, aún existe un beneficio semántico y estructural, y podría ser útil poder incluir / excluir un módulo con una sola línea de código comentada dentro o fuera.
También casi nunca tiene mucho sentido separar los submódulos por tipo (por ejemplo, ''myMapSubModule.controllers'') ya que generalmente dependen el uno del otro.