Html AngularJS 使用 $rootScope 作为数据存储
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16739084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS using $rootScope as a data store
提问by Chris Collins
I have an idea for my AngularJS app and I'm curious if the AngularJS community would consider it okay to do it this way. In short, I am connecting to a data API and displaying my results on the page.
我对我的 AngularJS 应用程序有一个想法,我很好奇 AngularJS 社区是否认为这样做可以。简而言之,我正在连接到数据 API 并在页面上显示我的结果。
I have created an AngularJS service that creates a data store on $rootScope.DataStore
. I also have a service method that updates the DataStore with the data returned from an API endpoint. If I request the "products" API endpoint from inside my controller with DataStore.update('products')
, this would update $rootScope.DataStore.products
with my product data.
我创建了一个 AngularJS 服务,它在$rootScope.DataStore
. 我还有一个服务方法,它使用从 API 端点返回的数据更新 DataStore。如果我从我的控制器内部请求“产品”API 端点DataStore.update('products')
,这将更新$rootScope.DataStore.products
我的产品数据。
Now, in the view/partial, all I need to do is say ng-repeat="product in DataStore.products"
to show my data, and it doesn't matter what controller scope I am in. So, in essence my DataStore is my single source of truth.
现在,在视图/部分中,我需要做的就是ng-repeat="product in DataStore.products"
显示我的数据,而我在哪个控制器范围内并不重要。因此,从本质上讲,我的 DataStore 是我的唯一事实来源。
What I feel like I gain from this method is easy to follow semantics and minimal controller coding. So, anytime the DataStore is updated, anything that's bound to DataStore also gets updated.
我觉得我从这种方法中获得的是易于遵循的语义和最少的控制器编码。因此,只要 DataStore 更新,任何绑定到 DataStore 的内容也会更新。
Would this put too much load on the $rootScope
digest cycle, or is this just an odd way to do it? Or is it a totally awesome way? :) Any comments are welcome.
这是否会给$rootScope
摘要循环带来过多的负担,或者这只是一种奇怪的方法?或者这是一种非常棒的方式?:) 欢迎提出任何意见。
回答by Dan
This question is addressed in the AngularJS FAQquoted here:
这个问题在此处引用的AngularJS 常见问题解答中得到解决:
Occasionally there are pieces of data that you want to make global to the whole app. For these, you can inject $rootScopeand set values on it like any other scope. Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like ng-show just like values on your local $scope.
有时,您希望将一些数据全局化到整个应用程序。对于这些,您可以像任何其他范围一样注入 $rootScope并在其上设置值。由于作用域继承自根作用域,因此这些值将可用于附加到诸如 ng-show 之类的指令的表达式,就像本地 $scope 上的值一样。
It seems that the team does encourage using $rootScope
this way, with this caveat:
似乎该团队确实鼓励使用$rootScope
这种方式,但有以下警告:
Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.
Conversely, don't create a service whose only purpose in life is to store and return bits of data.
当然,全局状态很糟糕,您应该谨慎使用 $rootScope,就像您(希望)在任何语言中与全局变量一起使用一样。特别是,不要将它用于代码,仅用于数据。如果您想将一个函数放在 $rootScope 上,那么将它放在一个可以注入到需要的地方并且更容易测试的服务中几乎总是更好。
相反,不要创建服务的唯一目的是存储和返回数据位。
This does not put too much load on the $digest
cycle (which implements basic dirty checking to test for data mutation) and this is not an odd way to do things.
这不会给$digest
循环带来太多负载(它实现了基本的脏检查以测试数据突变),而且这不是一种奇怪的做事方式。
EDIT:For more details on performance, see this answer from Misko (AngularJS dev) here on SO: How does data binding work in AngularJS?Specifically note the section on performance.
编辑:有关性能的更多详细信息,请参阅 Misko(AngularJS 开发人员)在 SO:数据绑定如何在 AngularJS 中工作?特别注意性能部分。
回答by Jordan Papaleo
To appease all parties, why not just use the $cacheFactory. This allows the data request services to be stateless and basically just a getter and setter. I will admit keeping the data on the $rootScope or as a property in the service is convenient but just feels wrong. Using the $cacheFactory is pretty easy too.
为了安抚各方,为什么不直接使用 $cacheFactory。这允许数据请求服务是无状态的,基本上只是一个 getter 和 setter。我承认将数据保存在 $rootScope 上或作为服务中的属性很方便,但感觉不对。使用 $cacheFactory 也很容易。
First create a cache service:
首先创建一个缓存服务:
angular.module('CacheService', ['ng'])
.factory('CacheService', function($cacheFactory) {
return $cacheFactory('CacheService');
});
Include the js file in in your app.js and then inject it into you app declaration:
在 app.js 中包含 js 文件,然后将其注入到您的应用声明中:
var MyApp = angular.module('MyApp', ['CacheService']);
Inject it in the service, use it like so:
将它注入到服务中,像这样使用它:
'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, '');
}
};
});
Now all that you have to do is inject your HackerNewsService in your controller and use it by calling the methods we created on it. For example:
现在您要做的就是将您的 HackerNewsService 注入您的控制器,并通过调用我们在其上创建的方法来使用它。例如:
HackerNewsService.setNews('myArticle', {headline: 'My Article', body: 'This is the body'});
$scope.article = HackerNewsService.getNews('myArticle');
回答by Ruben Decrop
My experience is that using the $rootScope for storing the part of my datamodel that is common to all ngViews in my app, is the most convenient way.
我的经验是,使用 $rootScope 存储应用程序中所有 ngView 共有的数据模型部分是最方便的方法。
<div>{{mymodel.property}}</div>
is for me more readable and shorter than
对我来说比
<div>{{getPropertyModel()}}</div>
with the javascript
使用 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;
};
}]);
If one uses a service or a cachefactory, every acces to the model in the html template becomes a function, which is less readable that a accessing a property of the rootScope. Using the $rootScope gives less code, and as a consequence less errors and less testing.
如果使用服务或缓存工厂,则对 html 模板中模型的每次访问都会变成一个函数,与访问 rootScope 的属性相比,它的可读性更低。使用 $rootScope 可以减少代码,从而减少错误和测试。
Of course only the common part of all ngView's is stored in $rootScope. The rest of the model is stored in the local $scope.
当然只有所有 ngView 的公共部分存储在 $rootScope 中。模型的其余部分存储在本地 $scope 中。
Watches on a function are also slower than on object properties. So performance-wise, $rootScope is also better.
对函数的监视也比对象属性慢。所以在性能方面, $rootScope 也更好。
回答by Matty J
I am just facing the same issue, and it seems to me that storing it ion globally available 'location' is the right approach, but that $rootScope is not the ideal place.
我只是面临同样的问题,在我看来,将它存储在全球可用的“位置”是正确的方法,但 $rootScope 不是理想的地方。
I have just been researching this more, and instead of storing your data on $rootScope, you could consider using a "service" to manage your data / separate concerns, as described here (especially the last code example): http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
我刚刚对此进行了更多研究,而不是将您的数据存储在 $rootScope 上,您可以考虑使用“服务”来管理您的数据/单独的关注点,如下所述(尤其是最后一个代码示例):http://joelhooks .com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
Then in the "service" you create using that approach, whether you save the data in memory, cacheFactory, localstorage(as alluded to here), and/or to your DB (eg. via AJAX), is up to whatever suits the needs of your app. It also means changes to how you store your data can be made independently, as required.
然后在“服务”您将使用这种方法,你是否保存在内存中,cacheFactory,数据localStorage的(如提到这里),和/或您的数据库(例如,通过AJAX),达到无论套装需要你的应用程序。这也意味着可以根据需要独立更改存储数据的方式。
回答by Jason
I guess I'm not sure why you need to use the rootScope? The lifetime of a service instance is the entire application as well, so whatever data schema / semantics you are using could also be stashed right in the service itself and it would be shared across controllers. Either of those methods however don't survive refresh like using local storage would.
我想我不确定为什么需要使用 rootScope?服务实例的生命周期也是整个应用程序,因此您使用的任何数据模式/语义也可以直接存储在服务本身中,并且可以在控制器之间共享。然而,这些方法中的任何一种都不能像使用本地存储那样在刷新后幸存下来。
The rest of it sounds like a lazy loading approach. Where the service is the only thing "aware" of whether the data has been loaded from the remote and returns it if it is already cached and caches and returns it if its not? If I understand that part correctly its a good pattern.
其余的听起来像是一种延迟加载方法。服务是唯一“知道”数据是否已从远程加载并在已经缓存的情况下返回它的地方,如果没有,则缓存并返回它?如果我正确理解那部分,它是一个很好的模式。
edit: Here I am taking a similar approach to the lazy loading, notice the cache is just in the service itself:
编辑:这里我对延迟加载采取了类似的方法,注意缓存只是在服务本身中:
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"));
},
};
})