58

我对我的 AngularJS 应用程序有一个想法,我很好奇 AngularJS 社区是否认为这样做可以。简而言之,我正在连接到数据 API 并在页面上显示我的结果。

我创建了一个 AngularJS 服务,它在$rootScope.DataStore. 我还有一个服务方法,它使用从 API 端点返回的数据更新 DataStore。如果我从我的控制器内部使用 请求“产品”API 端点DataStore.update('products'),这将$rootScope.DataStore.products使用我的产品数据进行更新。

现在,在视图/部分中,我需要做的就是ng-repeat="product in DataStore.products"显示我的数据,而我在哪个控制器范围内并不重要。所以,本质上,我的 DataStore 是我的单一事实来源。

我觉得我从这种方法中获得的好处是易于遵循语义和最少的控制器编码。因此,只要 DataStore 更新,绑定到 DataStore 的任何内容也会更新。

这会给消化周期带来太多负担$rootScope,还是这只是一种奇怪的方法?或者这是一个非常棒的方式?:) 欢迎任何意见。

4

5 回答 5

90

此处引用的AngularJS 常见问题解答中解决了这个问题:

有时,您想让某些数据对整个应用程序具有全局性。对于这些,您可以像任何其他范围一样注入 $rootScope并在其上设置值。由于作用域从根作用域继承,这些值将可用于附加到指令(如 ng-show)的表达式,就像本地 $scope 上的值一样。

似乎团队确实鼓励使用$rootScope这种方式,但需要注意的是:

当然,全局状态很糟糕,您应该谨慎使用 $rootScope,就像(希望)在任何语言中使用全局变量一样。特别是,不要将其用于代码,仅用于数据。如果您想在 $rootScope 上放置一个函数,最好将它放在一个可以在需要的地方注入并且更容易测试的服务中。

相反,不要创建一个生活中唯一目的是存储和返回数据位的服务。

这不会给循环带来太多负担$digest(它实现了基本的脏检查来测试数据突变),这并不是一种奇怪的做事方式。

编辑: 有关性能的更多详细信息,请在此处查看 Misko(AngularJS 开发人员)的答案:数据绑定在 AngularJS 中如何工作? 特别注意性能部分。

于 2013-05-24T16:11:21.627 回答
34

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

首先创建一个缓存服务:

angular.module('CacheService', ['ng'])
    .factory('CacheService', function($cacheFactory) {
    return $cacheFactory('CacheService');
});

在您的 app.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');
于 2013-10-01T15:10:01.247 回答
9

我的经验是,使用 $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;
    };
}]);

如果使用服务或缓存工厂,则对 html 模板中模型的每次访问都会变成一个函数,与访问 rootScope 的属性相比,它的可读性较差。使用 $rootScope 可以减少代码,从而减少错误和测试。

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

对函数的监视也比对对象属性的监视要慢。所以在性能方面,$rootScope 也更好。

于 2013-11-18T14:57:30.240 回答
0

我想我不确定你为什么需要使用 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"));
            },                
        };
    })
于 2013-05-24T16:11:36.533 回答
0

我只是面临同样的问题,在我看来,将它存储在全球可用的“位置”是正确的方法,但 $rootScope 不是理想的地方。

我刚刚对此进行了更多研究,而不是将您的数据存储在 $rootScope 上,您可以考虑使用“服务”来管理您的数据/单独的关注点,如此处所述(尤其是最后一个代码示例):http://joelhooks .com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/

然后在您使用该方法创建的“服务”中,无论您是否将数据保存在内存、cacheFactory、localstorage (如这里提到的)和/或您的数据库(例如,通过 AJAX)中,都取决于适合的需求您的应用程序。这也意味着可以根据需要独立更改存储数据的方式。

于 2013-10-11T03:19:12.527 回答