모듈 선언에 대한 AngularJS 모범 사례?


115

내 앱에 여러 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){ ... }]);
    ...
})();

아니면 돌보는 것이 충분히 중요합니까? 모듈 선언에 대한 "모범 사례"가 무엇인지 알고 싶습니다. 미리 감사드립니다.


3
나는 약 같은 궁금 각도 모범 사례
Dalorzo

답변:


118

모듈을 선언하는 '가장 좋은'방법

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){
      //..
  }])
})();

다른 전역 변수는 필요하지 않습니다.

물론 그것은 모두 선호도에 달려 있지만 이것이 최선의 방법이라고 생각합니다.

  1. 글로벌 스코프를 오염시킬 필요가 없습니다.
  2. 어디서나 모듈에 액세스하고 원하는대로 모듈과 기능을 다른 파일로 정렬 할 수 있습니다.
  3. "엄격한 사용"의 함수 형식을 사용할 수 있습니다.
  4. 파일의 로딩 순서는 그다지 중요하지 않습니다

모듈 및 파일 정렬 옵션

모듈을 선언하고 액세스하는이 방법은 매우 유연합니다. 함수 유형 (다른 답변에 설명 된 것과 같음) 또는 경로를 통해 모듈을 정렬 할 수 있습니다. 예 :

/******** 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'
]);

매우 큰 프로젝트의 경우, 위에서 설명한대로 라우트별로 모듈을 그룹화하거나 선택한 주요 라우트 또는 라우트와 일부 선택된 구성 요소의 조합으로도 그룹화하는 경우가 있지만 실제로는 다릅니다.

편집 : 관련이 있고 최근에 다시 만났기 때문에 모듈을 한 번만 생성 하십시오 (angular.module-function에 두 번째 매개 변수를 추가하여). 이것은 응용 프로그램을 엉망으로 만들고 감지하기가 매우 어려울 수 있습니다.

정렬 모듈에 대한 2015 편집 : 1 년 반의 각도 경험 이후, AMD가 Angular 및 서비스, 지시문 및 필터에서 여전히 잘 작동하지 않기 때문에 앱 내에서 이름이 다른 모듈을 사용하는 이점이 다소 제한적이라고 덧붙일 수 있습니다. 어쨌든 각도 컨텍스트 내에서 전역 적으로 사용할 수 있습니다 ( 여기에 예시 된대로 ). 그래도 의미 론적 및 구조적 이점이 있으며 한 줄의 코드가 주석 처리 된 모듈을 포함 / 제외 할 수 있으면 도움이 될 수 있습니다.

일반적으로 서로 의존하기 때문에 유형별로 하위 모듈을 분리하는 것도 거의 의미가 없습니다 (예 : 'myMapSubModule.controllers').


7
당신은 인생 (즉시 호출 기능 식), 일명 익명 자동 실행 기능이 필요하지 않습니다
플러스 -

1
네가 옳아. "엄격한 사용"의 기능 형식을 적용하려는 경우에만 필요합니다. 그래도 아프지 않습니다.
hugo der hungrige

1
대부분의 경우 'use strict';구성 요소 안에 넣을 수도 있습니다. module.controller(function () { 'use strict'; ... });
Jackson

나는 구현을 좋아하지만 연결하는 것도 재미 없다. 그래서 나는 이것을 Beterraba가하는 일과 혼합하고있다
Mirko

1
AMD를 사용할 때 app이라는 단일 모듈 하나면 충분합니다. require 문을 삭제하여 AMD 모듈을 제외 할 수 있습니다. 더 이상 컨트롤러와 서비스를 등록 할 필요가 없습니다.
James

28

저는 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.

규칙 : 파일 당 하나의 컴포넌트를 정의하십시오.

하나의 파일에 여러 구성 요소를 사용하지 마십시오.

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);

좋은 답변과 훌륭한 링크.
Ellesedil

다른 자바 스크립트 파일에 다른 컨트롤러가있는 경우 더 많은 수의 파일, 즉 더 많은 서버 히트를로드해야하지 않습니까?
Vignesh Subramanian 2015 년

gulp 또는 grunt, vignesh로 병합 / 추진 / 이름 바꾸기가 매우 쉽습니다.
aqingsao

1
추가하는 것을 잊었습니다.이 모든 스 니펫은 IIFE에 있어야합니다. 그렇지 않으면 전역 적으로 "someFactory ()"와 같은 함수가 있습니다. 이름 충돌 가능성이 있습니다. (그리고 es6에서는 IIFE가 필요하지 않습니다)
ya_dimon

12

최근에이 문제도있었습니다. 나는 체인 구문을 사용하는 것처럼 시작했지만 장기적으로는 대규모 프로젝트에서 다루기 어려워집니다. 일반적으로 컨트롤러 모듈, 서비스 모듈 등을 별도의 파일에 만들고 다른 파일에있는 기본 응용 프로그램 모듈에 삽입합니다. 예를 들면 :

// 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',[...]);

서비스 파일에도이 작업을 수행했습니다. 동일한 모듈을 여전히 삽입하는 주 응용 프로그램 모듈 파일을 변경할 필요가 없습니다.


1
서비스 / 지시문 / 컨트롤러에 대해 별도의 모듈을 만드는 이유는 무엇입니까?
Filip Sobczak

2
대규모 프로젝트에서 컨트롤러 / 필터 / 지시문 / 서비스가 모두 함께 인터리브되면 사물을 찾기가 어려울 수 있습니다. 이것은 일을 정리하는 한 가지 방법 일뿐입니다.
meconroy

1
@FilipSobczak 그는 서비스 / 지시문 / 컨트롤러를위한 별도의 모듈을 생성하지 않습니다. 오히려 그는 사용하여 한 번만 모듈을 만들었습니다 angular.module('my-controllers',[]);(선언을 위해 []를 한 번만 지정하고 있음에 유의하십시오). 그는 단순히 다른 파일에서 이것을 재사용하고 있습니다. 파일을 분리하면 프로젝트, 특히 큰 파일을 비교적 쉽게 유지 관리 할 수 ​​있습니다.
Devner

8

또 다른 방법은 컨트롤러, 지시문 등을 자체 모듈에 넣고 해당 모듈을 "주"모듈에 삽입하는 것입니다.

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


모듈 이름으로 app.controllersinsted 를 사용하는 이유는 무엇 controllers입니까? 나는 AngularJS와의 신인이야
시조 비제이 안

4

내 파일과 모듈을 나누는 것을 좋아합니다.

이 같은:

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( /* ... */ );

Im은 "체인 스타일"을 좋아하지 않기 때문에 항상 변수를 적어 두는 것을 선호합니다.


2
이것이 제가 해왔 던 방식이지만 각 services.js 또는 controller.js 파일은 대규모 프로젝트에서 빠르게 커지므로 결국 각 서비스 또는 컨트롤러를 별도의 파일로 분리해야합니다.
meconroy

1
@meconroy 정확합니다. 일이 점점 커지면 지시어를 더 작은 모듈로 나누고 "주"지시어 모듈에 주입하는 것을 좋아합니다.
Beterraba 2013


0

저에게있어 체인은 가장 간단한 방법입니다.

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 = ...;
 })
 ;

이렇게하면 모듈간에 구성 요소를 쉽게 이동할 수 있고 동일한 모듈을 두 번 선언 할 필요가 없으며 전역 변수가 필요하지 않습니다.

그리고 파일이 너무 길어지면 솔루션은 간단합니다. 두 개의 파일로 분할되고 각 파일은 맨 위에 자체 모듈을 선언합니다. 투명성을 높이기 위해 파일 당 하나의 고유 한 모듈을 유지하고 파일의 전체 경로와 비슷한 이름을 지정하려고합니다. 이런 식으로 나는 또한 []공통적 인 고통 포인트 인를 사용 하지 않고 모듈을 작성할 필요가 없습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.