AngularJS의 전역 변수


348

컨트롤러의 범위에서 변수를 초기화하는 데 문제가 있습니다. 그런 다음 사용자가 로그인 할 때 다른 컨트롤러에서 변경됩니다.이 변수는 탐색 표시 줄과 같은 항목을 제어하는 ​​데 사용되며 사용자 유형에 따라 사이트 일부에 대한 액세스를 제한하므로 값을 유지하는 것이 중요합니다. 문제는 그것을 초기화하는 컨트롤러가 어떻게 각도에 의해 다시 호출되어 변수를 초기 값으로 다시 설정한다는 것입니다.

나는 이것이 전역 변수를 선언하고 초기화하는 올바른 방법이 아니라고 가정합니다. 실제로 전역 적이 지 않습니다. 제 질문은 올바른 방법은 무엇이며 현재 버전의 각도에서 그 작동에 대한 좋은 예가 무엇입니까?


12
이것이 Google 검색 결과 # 1이므로 이제 app.constant () 및 app.value ()를 사용하여 앱 전체 상수 및 변수를 만들 수 있습니다. 여기 더 : bit.ly/1P51PED
Mroz

답변:


491

기본적으로 "전역"변수에 대한 두 가지 옵션이 있습니다.

$rootScope는 모든 범위의 부모이므로 노출 된 값은 모든 템플릿과 컨트롤러에 표시됩니다. $rootScope컨트롤러에 간단히 주입하고이 범위에서 값을 변경할 수 있으므로를 사용하는 것은 매우 쉽습니다. 편리하지만 전역 변수의 모든 문제가 있습니다 .

서비스는 모든 컨트롤러에 주입하고 해당 값을 컨트롤러 범위에 노출 할 수있는 싱글 톤입니다. 싱글 톤 인 서비스는 여전히 '전세계'이지만 서비스가 사용되고 노출되는 위치를 훨씬 잘 제어 할 수 있습니다.

서비스 사용은 좀 더 복잡하지만 그다지 많지는 않습니다.

var myApp = angular.module('myApp',[]);
myApp.factory('UserService', function() {
  return {
      name : 'anonymous'
  };
});

그런 다음 컨트롤러에서 :

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
}

작동하는 jsFiddle은 다음과 같습니다. http://jsfiddle.net/pkozlowski_opensource/BRWPM/2/


141
로부터 각도 자주 묻는 질문 : 반대로, 그의 유일한 목적은 인생에서 데이터의 저장 및 복귀 비트있는 서비스를 만들 수 없습니다.
야콥 스토크

7
BtfordExpress + Angular seed를 사용하고 있습니다. Controller1에서 $ rootScope에 변수를 설정하고 다른 URL로 이동하면 (Controller2에서 제공)이 변수에 액세스 할 수 있습니다. 그러나 Controller2에서 페이지를 새로 고치면 변수는 더 이상 $ rootScope에서 액세스 할 수 없습니다. 로그인시 사용자 데이터를 저장하는 경우 페이지를 새로 고치더라도 다른 곳에서이 데이터에 액세스 할 수 있도록하려면 어떻게해야합니까?
Craig Myles

19
@JakobStoeck이 답변을이 답변과 결합하면 rootScope에 데이터를 넣을 수 있습니다. 나는 그것이 옳다고 생각하지 않습니다. 전 세계적으로 사용되는 데이터 비트를 저장하고 반환하는 각도 방법은 무엇입니까?
user2483724

11
특히 값을 저장하는 서비스의 단점이 무엇인지 궁금합니다. 절연되어 필요한 곳에만 주입하고 쉽게 테스트 할 수 있습니다. 단점은 무엇입니까?
Brian

12
오 세상에, 왜 모든 사람이 현실 세계 변수를 두려워하는지, 왜 앱이 무엇으로 구성되어 있는지 알고 있다면, 과도하게 복잡하게 만드는 실제 전역 js 변수를 만드십시오
Max Yari

93

공급자Angular 설명서에 따라 값을 저장 하려면 값 레시피를 사용해야합니다.

var myApp = angular.module('myApp', []);
myApp.value('clientId', 'a12345654321x');

그런 다음 다음과 같은 컨트롤러에서 사용하십시오.

myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
}]);

제공자, 팩토리 또는 서비스는 "프로 바이더 레시피 위에 구문 설탕"이기 때문에 동일한 것을 얻을 수 있지만 Value를 사용하면 최소한의 구문으로 원하는 것을 얻을 수 있습니다.

다른 옵션은을 사용하는 $rootScope것이지만 다른 언어에서 전역 변수를 사용해서는 안되는 것과 같은 이유로 사용해서는 안되기 때문에 실제로는 옵션이 아닙니다. 있어 좋습니다 아껴서 사용할 수 있습니다.

모든 범위가에서 상속되므로 $rootScope변수가 $rootScope.data있고 누군가 data가 이미 정의 $scope.data되어 있고 로컬 범위에서 생성 된 것을 잊어 버리면 문제가 발생합니다.


이 값을 수정하고 모든 컨트롤러에서 유지하려면 객체를 사용하고 속성을 수정하십시오. Javascript는 "참조의 복사"를 통해 전달됩니다 .

myApp.value('clientId', { value: 'a12345654321x' });
myApp.controller('DemoController', ['clientId', function DemoController(clientId) {
    this.clientId = clientId;
    this.change = function(value) {
        clientId.value = 'something else';
    }
}];

JSFiddle 예제


1
한보기에서 값을 변경하면 새 값이 영구적이지 않습니다. 어떻게 오세요? 답변을 업데이트하고 업데이트 방법을 알려 주 clientId시겠습니까?
Blaise

@DeanOr 페이지를 새로 고칠 때마다 업데이트 된 값을 유지할 수 있습니까? 페이지를 새로 고치면 값이 다시 초기화됩니다.
Nabarun

쿠키, 로컬 스토리지 또는 데이터베이스와 같은 다른 것을 사용해야합니다.
Dean 또는

1
나는 이것을 가장 좋아합니다. 지금은 dev에, 무대, 그리고 자극에 대한 빌드 프로세스에 의해 수정할 수 있습니다
jemiloii

1
글로벌 변수와 유사한 상수 및 값 사용을 설명하는 간단한 기사가 있습니다. ilikekillnerds.com/2014/11/…
RushabhG

36

다음을 사용하는 AngularJS "글로벌 변수"의 예 $rootScope:

제어기 1은 전역 변수를 설정합니다.

function MyCtrl1($scope, $rootScope) {
    $rootScope.name = 'anonymous'; 
}

컨트롤러 2는 전역 변수를 읽습니다.

function MyCtrl2($scope, $rootScope) {
    $scope.name2 = $rootScope.name; 
}

작동하는 jsFiddle은 다음과 같습니다. http://jsfiddle.net/natefriedman/3XT3F/1/


2
분리 된 범위 지시문의 관점에서는 작동하지 않습니다. jsfiddle.net/3XT3F/7을 참조하십시오 . 그러나 $ root를 사용하여 해결할 수 있습니다. jsfiddle.net/3XT3F/10을 참조하십시오 . 그것을 지적 해 주신 @natefaubion 에게 감사드립니다
Tony Lâmpada

2
새로 고치면 $ rootScope 값이 비어 있습니다.
xyonme

$ rootScope.name 하드 코딩은 일부 값과 같습니다. 실제로 우리는 그것을 읽고 거기에 설정해야합니다.

25

위키 풀에 다른 아이디어를 추가하고 싶지만 AngularJS valueconstant모듈은 어떻습니까? 나는 단지 그들 자신을 사용하기 시작했지만, 이것이 아마도 최고의 옵션 인 것처럼 들린다.

참고 : 글을 쓰는 시점에서 Angular 1.3.7은 최신 안정 버전입니다.

몇 개를 정의해야하는지에 따라 별도의 파일을 만들 수 있습니다. 그러나 일반적으로 .config()쉽게 액세스 할 수 있도록 앱 블록 바로 앞에 이것을 정의 합니다. 이것들은 여전히 ​​효과적인 모듈이기 때문에 의존성 주입을 사용하여 사용해야하지만 앱 모듈에 대한 "전역"으로 간주됩니다.

예를 들면 다음과 같습니다.

angular.module('myApp', [])
  .value('debug', true)
  .constant('ENVIRONMENT', 'development')
  .config({...})

그런 다음 컨트롤러 내부에서

angular.module('myApp')
  .controller('MainCtrl', function(debug, ENVIRONMENT), {
    // here you can access `debug` and `ENVIRONMENT` as straight variables
  })

초기 질문에서 실제로 정적 속성이 변경 가능한 값 (값) 또는 최종 (일정한)과 같이 필요한 것처럼 들립니다. 그것은 다른 어떤 것보다 개인적인 견해이지만, 런타임 구성 항목을 $rootScope너무 복잡하고 너무 빨리 배치하는 것을 발견했습니다 .


가치 모듈이 매우 유용하고 간결하다는 것을 알았습니다. 특히 컨트롤러 내 $ scope 변수에 바인딩 할 때 해당 컨트롤러의 논리 나 뷰 내 변경 사항이 전역 변수 / 값 / 서비스에 바인딩됩니다.
Ben Wheeler

20
// app.js or break it up into seperate files
// whatever structure is your flavor    
angular.module('myApp', [])    

.constant('CONFIG', {
    'APP_NAME' : 'My Awesome App',
    'APP_VERSION' : '0.0.0',
    'GOOGLE_ANALYTICS_ID' : '',
    'BASE_URL' : '',
    'SYSTEM_LANGUAGE' : ''
})

.controller('GlobalVarController', ['$scope', 'CONFIG', function($scope, CONFIG) {

    // If you wish to show the CONFIG vars in the console:
    console.log(CONFIG);

    // And your CONFIG vars in .constant will be passed to the HTML doc with this:
    $scope.config = CONFIG;
}]);

HTML에서 :

<span ng-controller="GlobalVarController">{{config.APP_NAME}} | v{{config.APP_VERSION}}</span>

8
localStorage.username = 'blah'

최신 브라우저를 사용하는 것이 보장됩니다. 당신의 가치는 모두 문자열로 바뀔 것입니다 알고 있지만.

또한 재로드간에 캐시되는 편리한 이점이 있습니다.


5
Heh, localStorage를 통해 모든 변수를 저장하겠습니다. 우리는 심지어 어떤 종류의 지속성을 가질 것입니다! 또한 문자열 제한을 해결하려면 함수의 .toString ()을 저장하고 필요할 때 평가하십시오!
Shaz

@Shaz에 의해 이미 언급 된 바와 같이, 이것은 지속성의 문제가있다
Żubrówka

7

내가 틀렸다면 나를 수정하십시오. 그러나 Angular 2.0이 출시 될 때 나는 $rootScope주변에있을 것이라고 믿지 않습니다 . 내 추측은 $scope제거되고 있다는 사실에 근거 하고 있습니다. 분명히 컨트롤러는 ng-controller유행이 아닌 여전히 존재합니다 . 대신 컨트롤러를 지시문에 주입하는 것을 고려하십시오. 릴리스가 임박 했으므로 verison 1.X에서 2.0으로보다 쉽게 ​​전환하려면 서비스를 전역 변수로 사용하는 것이 가장 좋습니다.


데이터를 $ rootScope에 직접 넣는 것은 Angular의 전체 목적에 위배됩니다. 약간의 시간이 걸리고 코드를 올바르게 구성하면 AngularJS 2.x 업그레이드뿐만 아니라 일반적으로 앱이 더 복잡 해짐에 따라 앱 개발에 도움이됩니다.
CatalinBerta

3
$ rootScope가 제거되면 "$ rootScope"라는 새 서비스를 작성하십시오.
uylmz

3

환경 변수를 사용하여 $window컨트롤러 외부의 전역 변수 선언을 내부에서 확인할 수 있습니다.$watch

var initWatch = function($scope,$window){
    $scope.$watch(function(scope) { return $window.globalVar },
        function(newValue) {
            $scope.updateDisplayedVar(newValue);
    });
}

주의해서, 다이제스트주기는 이러한 전역 값으로 길어 지므로 항상 실시간으로 업데이트되는 것은 아닙니다. 이 구성으로 다이제스트 시간을 조사해야합니다.


0

실수로 다른 방법을 찾았습니다.

내가 한 것은 var db = null위의 앱 선언을 선언하고 그때에 수정 app.js했을 때 controller.js 문제없이 액세스 할 수있었습니다.이 방법에는 알지 못하지만 몇 가지 문제가있을 수 있습니다. 좋은 해결책이라고 생각합니다.


0

이것을 시도하면 $rootScope컨트롤러에 강제로 주입하지 않습니다 .

app.run(function($rootScope) {
    $rootScope.Currency = 'USD';
});

구성 블록은 $ rootScope의 서비스를 제공하지 않으므로 실행 블록에서만 사용할 수 있습니다.


0

실제로는 매우 쉽습니다. (어쨌든 Angular 2 이상을 사용하는 경우)

간단히 추가

declare var myGlobalVarName;

구성 요소 파일 상단 (예 : "import"문 다음)에 있으면 구성 요소 내부의 "myGlobalVarName"에 액세스 할 수 있습니다.


-2

당신은 또한 이런 일을 할 수 있습니다 ..

function MyCtrl1($scope) {
    $rootScope.$root.name = 'anonymous'; 
}

function MyCtrl2($scope) {
    var name = $rootScope.$root.name;
}

3
이 방법으로 사용할 경우 $ rootScope는 정의되지 않습니다.
Ahmad Ahmadi 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.