У меня есть идея для моего приложения AngularJS, и мне любопытно, будет ли сообщество AngularJS рассматривать это нормально, чтобы сделать это таким образом...
Короче говоря, я подключаюсь к API данных и показываю результаты на странице. Я создал службу angular, которая создает хранилище данных в $rootScope.DataStore. У меня также есть метод службы, который обновляет DataStore с данными, возвращаемыми с конечной точки API. Если я запрошу конечную точку API "продуктов" из моего контроллера с помощью DataStore.update( "продукты" ), это приведет к обновлению данных $rootScope.DataStore.products с данными моего продукта. Теперь, в представлении/частичном, все, что мне нужно сделать, это сказать ng-repeat = "product in DataStore.products", чтобы показать мои данные, и не имеет значения, в какой области контроллера я нахожусь. Таким образом, по существу мой DataStore мой единственный источник истины.
Я чувствую, что получаю от этого метода легко следовать семантике и минимальному кодированию контроллера. Таким образом, в любое время, когда DataStore обновляется, все, что связано с DataStore, также обновляется.
Будет ли это слишком сильно загружаться в цикл digest $rootScope, или это просто странный способ сделать это? Или это потрясающе?:) Любые комментарии приветствуются.
Ответ 1
Этот вопрос рассматривается в Часто задаваемые вопросы по AngularJS:
Иногда есть фрагменты данных, которые вы хотите сделать глобальными все приложение. Для этого вы можете вводить $rootScope и устанавливать значения на он, как и любая другая область. Поскольку области, наследуемые от области корня, эти значения будут доступны выражениям, прилагаемым к директивы, такие как ng-show, точно так же, как значения в локальной области $scope.
Кажется, что команда поощряет использование $rootScope
таким образом, с этим предупреждением:
Конечно, глобальное состояние отстойно, и вы должны использовать $rootScope экономно, как вы бы (надеюсь) использовали с глобальными переменными на любом языке. В частности, не используйте его для кода, а только данные. Если у вас возникает соблазн положил функцию на $rootScope, почти всегда лучше положить ее в услуги, которые можно вводить там, где это необходимо, и более легко тестирование.
И наоборот, не создавайте службу, единственной целью которой является хранить и возвращать бит данных.
Это не слишком сильно нагружает цикл $digest
(который реализует базовую грязную проверку для проверки мутации данных), и это не странный способ сделать что-то.
EDIT: Подробнее об эффективности см. в этом ответе от Misko (AngularJS dev) здесь, на SO: Как работает привязка данных в AngularJS? Обратите внимание на раздел о производительности.
Ответ 2
Чтобы успокоить всех сторон, почему бы просто не использовать $cacheFactory. Это позволяет службам запросов данных быть без гражданства и в основном просто получателем и установщиком. Я признаю, что хранить данные на $rootScope или как свойство в сервисе удобно, но просто чувствует себя не так. Использование $cacheFactory довольно просто.
Сначала создайте службу кеша:
angular.module('CacheService', ['ng'])
.factory('CacheService', function($cacheFactory) {
return $cacheFactory('CacheService');
});
Включите js файл в свой app.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');
Ответ 3
Мой опыт заключается в том, что использование $rootScope для хранения части моей datamodel, которая является общей для всех ngView в моем приложении, является наиболее удобным способом.
<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;
};
}]);
Если вы пользуетесь службой или кешью, каждый доступ к модели в html-шаблоне становится функцией, которая менее читаема, чтобы получить доступ к свойству rootScope. Использование $rootScope дает меньше кода и, как следствие, меньше ошибок и меньше тестирования.
Конечно, только общая часть всего ngView хранится в $rootScope. Остальная часть модели хранится в локальной области $.
Часы на функции также медленнее, чем на свойства объекта. Таким образом, лучше работать с $rootScope.
Ответ 4
Я думаю, я не уверен, зачем вам нужно использовать 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"));
},
};
})
Ответ 5
Я просто сталкиваюсь с одной и той же проблемой, и мне кажется, что сохранение ее глобального доступного "местоположения" является правильным подходом, но этот $rootScope не является идеальным местом.
Я только что исследовал это больше, и вместо того, чтобы хранить ваши данные в $rootScope, вы можете рассмотреть возможность использования "службы" для управления своими данными/отдельными проблемами, как описано здесь (особенно последний пример кода): http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
Затем в "службе", которую вы создаете с использованием этого подхода, сохраняете ли вы данные в памяти, cacheFactory, localstorage (как указано в здесь) и/или в вашу БД (например, через AJAX), зависит от потребностей вашего приложения. Это также означает, что изменения в том, как вы храните свои данные, могут быть сделаны независимо, по мере необходимости.