Глобальные переменные в AngularJS



У меня есть проблема, когда я инициализирую переменную на области в контроллере. Затем он изменяется в другом контроллере, когда пользователь входит в систему. Эта переменная используется для управления такими вещами, как панель навигации, и ограничивает доступ к частям сайта в зависимости от типа пользователя, поэтому важно, чтобы она сохраняла свое значение. Проблема с этим заключается в том, что контроллер, который инициализирует его, снова вызывается angular some how, а затем сбрасывает переменную обратно к ее исходному значению.



Я предполагаю, что это не правильный способ объявления и инициализации глобальных переменных, ну его не совсем глобальный, поэтому мой вопрос в том, что это правильный способ и есть ли хорошие примеры вокруг этой работы с текущей версией angular?

593   12  

12 ответов:

у вас есть в основном 2 варианта для "глобальных" переменных:

$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/

если вы просто хотите сохранить значение, согласно угловая документация на провайдеров, вы должны использовать рецепт значение:

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

пример 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/

в интересах добавления еще одной идеи в пул Вики, но как насчет AngularJS'value и constant? Я только начал использовать их сам, но мне кажется, что это, вероятно, лучшие варианты здесь.

Примечание: На момент написания, угловой 1.3.7 является последней стабильной, я считаю, что они были добавлены в 1.2.0, не подтвердили это с changelog, хотя.

в зависимости от того, сколько вам нужно определите, вы можете создать для них отдельный файл. Но я обычно определяю их непосредственно перед моим приложением .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 слишком сумбурно, слишком быстро.

// 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>

пожалуйста, поправьте меня, если я ошибаюсь, но когда угловой 2.0 выпущен я не верю$rootScope будет вокруг. Моя гипотеза основана на том, что $scope также удаляется. Очевидно, контроллеры, все равно будут существовать, только не в ng-controller моды.Вместо этого подумайте о введении контроллеров в директивы. Поскольку выпуск неизбежен, лучше всего будет использовать службы в качестве глобальных переменных, если вы хотите упростить переход от версии 1.X до 2.0.

localStorage.username = 'blah'

Если вы гарантированно находитесь в современном браузере. Хотя знайте, что все ваши значения будут превращены в строки.

также имеет удобное преимущество кэширования между перезагрузками.

вы также можете использовать переменную среды $window Так что глобальная переменная, объявленная вне контроллера, может быть проверена внутри $watch

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

Becareful, цикл дайджеста длиннее с этими глобальными значениями, поэтому он не всегда обновляется в реальном времени. Мне нужно исследовать это время дайджеста с этой конфигурацией.

Я просто нашел другой метод по ошибке:

то, что я сделал, было объявить a var db = null выше объявление приложения, а затем изменить его в app.js затем, когда я получил доступ к нему в controller.js Я смог получить к нему доступ без каких-либо проблем.Там могут быть некоторые проблемы с этим методом, о которых я не знаю, но это хорошее решение, я думаю.

попробуйте это, вы не заставите впрыснуть $rootScope в контроллер.

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

вы можете использовать его только в run block, потому что config block не предоставит вам использовать сервис $rootScope.

Это на самом деле довольно легко. (Если вы используете угловой 2+ в любом случае.)

просто добавить

declare var myGlobalVarName;

где-то в верхней части файла компонента (например, после операторов "импорт"), и вы сможете получить доступ к "myGlobalVarName" в любом месте внутри вашего компонента.

вы также можете сделать что-то подобное ..

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

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

Comments

    Ничего не найдено.