AngularJS использует $rootScope в качестве хранилища данных
У меня есть идея для моего приложения AngularJS, и мне любопытно, если сообщество AngularJS сочтет это нормальным, чтобы сделать это таким образом...
короче говоря, я подключаюсь к API данных и показываю свои результаты на странице. Я создал угловой сервис, который создает хранилище данных на метрики.хранилище данных. У меня также есть метод службы, который обновляет хранилище данных с данными, возвращенными из конечной точки API. Если я запрошу конечную точку API" продукты " изнутри моего контроллера с помощью хранилище данных.обновление ("продукты"), это обновит $rootScope.хранилище данных.продукты с моими данными о продукте. Теперь, в представлении / partial, все, что мне нужно сделать, это сказать ng-repeat="продукт в хранилище данных.продукты", чтобы показать мои данные, и не имеет значения, в какой области контроллера я нахожусь. Итак, по сути, мое хранилище данных - это мой единственный источник истины.
то, что я чувствую, что я получаю от этого метода, легко следовать семантике и минимальному кодированию контроллера. Итак, в любое время, когда хранилище данных обновляется, все, что связано в хранилище данных также обновляется.
будет ли это слишком большой нагрузкой на цикл $ rootScope digest, или это просто странный способ сделать это? Или это совершенно потрясающий способ? :) Любые комментарии приветствуются.
5 ответов:
этот вопрос рассматривается в разделе в AngularJS часто задаваемые вопросы цитировал здесь:
иногда есть фрагменты данных, которые вы хотите сделать глобальными все приложение. За это ты можно ввести $rootScope и задать значения это как и любой другой объем. Поскольку области наследуются от корневой области, эти значения будут доступны для выражений, присоединенных к директивы, такие как ng-показать так же, как значения на вашем локальном $масштаб.
похоже, что команда поощряет использование
$rootScope
таким образом, с этой оговоркой:конечно, глобальное состояние отстой, и вы должны использовать $rootScope экономно, как вы бы (надеюсь) использовать с глобальными переменными на любом языке. В частности, не используйте его для кода, только данные. Если вы склонны поместите функцию на $rootScope, почти всегда лучше поместить ее в a обслуживание которое можно впрыснуть где оно необходимо, и более легко проверенный.
и наоборот, не создавайте сервис, единственной целью которого в жизни является хранить и возвращать биты данных.
это не ставит слишком много нагрузки на
$digest
цикл (который реализует базовую грязную проверку для проверки мутации данных), и это не странный способ делать вещи.EDIT: для получения более подробной информации о производительности см. Этот ответ от Misko (AngularJS dev) здесь:как работает привязка данных AngularJS? особенно обратите внимание на раздел о производительности.
чтобы успокоить все стороны, почему бы просто не использовать $cacheFactory. Это позволяет службам запроса данных быть без состояния и в основном просто геттер и сеттер. Я признаю, что хранение данных на $rootScope или как свойство в сервисе удобно, но просто чувствует себя неправильно. Использование $cacheFactory тоже довольно легко.
сначала создайте службу кэша:
angular.module('CacheService', ['ng']) .factory('CacheService', function($cacheFactory) { return $cacheFactory('CacheService'); });
включите файл js в свое приложение.js, а затем ввести его в приложение объявление:
var MyApp = angular.module('MyApp', ['CacheService']);
введите его в сервис, используйте его так:
'use strict' MyApp.factory('HackerNewsService', function(CacheService) { return { getNews: function(key) { var news = CacheService.get(key); if(news) { return news; } return null; }, setNews: function(key, value) { CacheService.put(key, value); }, clearNews: function(key) { CacheService.put(key, ''); } }; });
теперь все, что вам нужно сделать, это ввести свой HackerNewsService в контроллер и использовать его, вызывая методы, которые мы создали на нем. Например:
HackerNewsService.setNews('myArticle', {headline: 'My Article', body: 'This is the body'}); $scope.article = HackerNewsService.getNews('myArticle');
мой опыт заключается в том, что использование $rootScope для хранения части моей модели данных, которая является общей для всех ngViews в моем приложении, является наиболее удобным способом.
<div>{{mymodel.property}}</div>
является для меня более читаемым и короче, чем
<div>{{getPropertyModel()}}</div>
С помощью javascript
app.factory('MyModel', function(){ return { getModel: function() { ... }, setModel: function(m) { ... }, } }); app.controller('ctrl', ['$scope', 'MyModel', function($scope, MyModel){ $scope.getPropertModel = function() { return MyModel.getModel().property; }; }]);
Если вы используете сервис или cachefactory, каждый доступ к модели в шаблоне html становится функцией, которая менее читаема, чем доступ к свойству rootScope. С помощью метрики дает меньше кода, и как следствие меньше ошибок и меньше тестов.
конечно, только общая часть всех ngView хранится в $rootScope. Остальная часть модели хранится в локальной области$.
часы на функции также медленнее, чем на свойства объекта. Таким образом, с точки зрения производительности, $rootScope также лучше.
Я думаю, я не уверен, почему вам нужно использовать rootScope? Время жизни экземпляра службы-это также все приложение, поэтому любая схема данных / семантика, которую вы используете, также может быть спрятана прямо в самой службе, и она будет совместно использоваться между контроллерами. Однако любой из этих методов не выдерживает обновления, как при использовании локального хранилища.
остальное звучит как ленивый подход к загрузке. Где служба только что "в курсе" того данные были загружены с пульта дистанционного управления и возвращает его, если он уже кэшируется и кэширует и возвращает его, если его нет? Если я правильно понимаю эту часть, это хороший образец.
изменить: Здесь я использую аналогичный подход к ленивой загрузке, обратите внимание, что кэш находится только в самой службе:
angular.module('HN_Reddit_Mashup.Services', []) .factory('HackerNews', function($http) { var HackerNewsCache = {}; return { get: function(url) { return HackerNewsCache[url] || (HackerNewsCache[url] = $http.jsonp("http://api.thriftdb.com/api.hnsearch.com/items/_search?q=" + url + "&callback=JSON_CALLBACK")); }, }; })
Я просто сталкиваюсь с той же проблемой, и мне кажется, что хранение его в глобально доступном "местоположении" является правильным подходом, но что $rootScope не является идеальным местом.
Я только что исследовал это больше, и вместо того, чтобы хранить ваши данные на $rootScope, вы можете рассмотреть возможность использования "службы" для управления вашими данными / отдельными проблемами, как описано здесь (особенно последний пример кода): http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
затем в "сервисе", который вы создаете, используя этот подход, сохраняете ли Вы данные в памяти, cacheFactory, localstorage (как говорил здесь), и/или к вашей БД (например. через AJAX), до того, что соответствует потребностям вашего приложения. Это также означает, что изменения в способе хранения данных могут быть сделаны независимо, по мере необходимости.