AngularJS使用$ rootScope作为数据存储

我有一个AngularJS应用程序的想法,我很好奇,如果AngularJS社区会认为这样做可以… … –

总之,我连接到一个数据API并在页面上显示我的结果。 我创build了一个在$ rootScope.DataStore上创build数据存储的angular度服务。 我也有一个服务方法,用从API端点返回的数据更新DataStore。 如果我使用DataStore.update('products')从控制器请求“products”API端点,则会使用我的产品数据更新$ rootScope.DataStore.products。 现在,在视图/部分中,我只需要说ng-repeat =“DataStore.products中的产品”来显示我的数据,而不pipe我在哪个控制器范围内。所以,本质上我的DataStore是我真实的唯一来源。

我觉得从这个方法中获得的东西很容易遵循语义和最小的控制器编码。 因此,无论DataStore何时更新,绑定到DataStore的任何内容都会被更新。

这会给$ rootScope digest循环带来太多的负担吗?或者这只是一个奇怪的方式来做到这一点? 或者这是一个完全真棒的方式? :)欢迎任何评论。

这个问题在这里引用的AngularJS FAQ中得到解决:

偶尔会有一些数据要在整个应用程序中使用。 对于这些,您可以注入$ rootScope并像其他任何作用域一样设置值。 由于作用域inheritance自根作用域,因此这些值将可用于像ng-show这样的指令附加的expression式,就像本地$ scope中的值一样。

看来这个团队鼓励用这种方式使用$rootScope ,这个警告:

当然,全局状态很糟糕,你应该谨慎使用$ rootScope,就像你希望用任何语言的全局variables一样。 特别是,不要使用它的代码,只有数据。 如果您试图在$ rootScope上放置一个函数,那么把它放在一个可以注入需要的地方的服务中会更好,而且更容易testing。

相反,不要创build一个唯一的目的是存储和返回数据的服务。

这不会在$digest循环(它实现基本的脏检查来testing数据变异)上加载太多的负载,这不是一个奇怪的方式来做事情。

编辑:有关性能的更多细节,请参阅Misko(AngularJS dev)的这个答案: 在AngularJS中数据绑定是如何工作的? 特别注意性能部分。

为了安抚各方,为什么不使用$ cacheFactory。 这允许数据请求服务是无状态的,基本上只是一个getter和setter。 我会承认将数据保存在$ rootScope中,或者作为服务中的一个属性很方便,但感觉不对。 使用$ cacheFactory也很容易。

首先创build一个caching服务:

 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,并通过调用我们创build的方法来使用它。 例如:

 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属性的可读性就会降低。 使用$ rootScope可以减less代码,从而减less错误和减lesstesting。

当然,只有所有ngView的公共部分存储在$ rootScope中。 模型的其余部分存储在本地$ scope中。

手表上的function也比对象属性慢。 所以性能方面,$ rootScope也更好。

我想我不知道为什么你需要使用rootScope? 服务实例的生命周期也是整个应用程序,所以无论您使用的是什么数据模式/语义,都可以在服务本身中保存,并且可以在控制器之间共享。 然而,这些方法中的任何一个都不能像使用本地存储那样存在刷新。

其余的听起来像一个懒惰的加载方法。 服务是唯一“意识到”数据是否已经从远程装载并返回它,如果它已经被caching,并caching并返回它,如果它不是? 如果我正确理解这一部分是一个好的模式。

编辑:在这里,我正在采取类似的方法进行延迟加载,注意caching只是在服务本身:

 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上,你可以考虑使用一个“服务”来pipe理你的数据/单独的问题,如下所述(尤其是最后一个代码示例): http:// joelhooks .COM /博客/ 2013/04/24 /模拟数据和状态,在你的angularjs应用程序/

然后在使用这种方法创build的“服务”中,无论是将数据保存在内存,cacheFactory, localstorage (如这里所提及的)和/或数据库(例如通过AJAX)中,都可以满足任何需求的应用程序。 这也意味着如何根据需要独立地更改存储数据的方式。