我对AngularJS应用有个主意,我很好奇AngularJS社区是否认为可以这样做。简而言之,我正在连接到数据API并将结果显示在页面上。
我创建了一个AngularJS服务,该服务在$rootScope.DataStore
上创建了一个数据存储。我还有一个服务方法,可以使用从API端点返回的数据更新DataStore。如果我从控制器内部使用DataStore.update('products')
请求“ products” API端点,则将使用我的产品数据更新$rootScope.DataStore.products
。
现在,在视图/部分视图中,我只需要说ng-repeat="product in DataStore.products"
即可显示我的数据,而我所处的控制器范围并不重要。因此,实质上,我的DataStore是我唯一的真理来源。
我从这种方法中所获得的收获是易于理解的语义和最少的控制器编码。因此,无论何时更新DataStore,绑定到DataStore的任何内容也会被更新。
这是否会在$rootScope
摘要周期上增加过多的负载,或者这只是一种奇怪的方法?还是这是一种很棒的方式? :)欢迎任何评论。
此问题在AngularJS FAQ中引用:
有时,您需要全局设置某些数据整个应用。对于这些,您可以注入$ rootScope并在就像其他作用域一样由于范围继承自根范围,这些值可用于附加到的表达式像ng-show这样的指令就像本地$ scope上的值一样。
似乎团队确实鼓励这种方式使用$rootScope
,但要注意:
当然,全局状态很糟糕,您应该谨慎使用$ rootScope,就像您(希望)使用任何语言的全局变量一样。特别是,不要将其用于代码,而仅用于数据。如果你很想将函数放在$ rootScope上,将其放在一个目录中几乎总是更好可以在需要的地方更轻松地注入服务经过测试。
相反,请勿创建服务的唯一目的是存储并返回数据位。
[这不会给$digest
周期带来太大的负担(该周期实现了基本的脏检查以测试数据突变),而且这并不是一种奇怪的处理方式。
EDIT:有关性能的更多详细信息,请参见Misko(AngularJS开发人员)的关于SO的答案:How does data binding work in AngularJS?特别注意性能部分。
为了安抚各方,为什么不只使用$ 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');
[我的经验是,使用$ rootScope存储我的数据模型中应用程序中所有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;
};
}]);
如果使用服务或cachefactory,则html模板中的每个模型都将成为一种函数,与访问rootScope的属性相比,其可读性较低。使用$ rootScope可以减少代码量,从而减少错误和测试。
当然,所有ngView的公共部分都存储在$ rootScope中。模型的其余部分存储在本地$ scope中。
函数上的监视也比对象属性上的监视慢。因此,从性能角度来看,$ 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(指here)和/或数据库(例如,通过AJAX)中,满足您应用程序的需求。这也意味着可以根据需要独立地更改数据存储方式。