【问题标题】:shared state between controllers - angularjs控制器之间的共享状态 - angularjs
【发布时间】:2015-05-14 11:17:14
【问题描述】:

关于控制器之间的共享状态。我很难从 SO 上推荐的所有可能解决方案中找到 正确 的方法。我制作这个草图是为了说明到目前为止我使用工厂对此的基本想法。

有一个工厂myFactory,它拥有一个共享变量sharedVar

Ctrl1, Ctrl2, Ctrl3 的控制器希望始终访问更新的版本。他们也可以拨打updateViaHttp

  1. 这是正确的工厂目的吗? (一般来说共享状态, 特定于服务和提供者等其他选项)

  2. 如果是这样,如何正确观察sharedVar的变化? (经过 对象的引用,$watch,事件(广播,开启),...)

  3. 是否有适合对象、数组和 原语

【问题讨论】:

    标签: angularjs


    【解决方案1】:
    1. 您的基本概念是正确的,假设“工厂”是指“服务”——我知道这有点令人困惑,因为服务是使用工厂函数声明的。也就是说,这是一个重要的区别,以便您可以更轻松地查找文档等。

    2. 观察变化要么通过使用对象引用并注意watch depths in Angular(我的首选方法),要么通过显式注册 $watch 语句(仍然注意观察深度)。一般来说,我认为你不应该过度使用广播,因为它会使你的代码有点混乱。在这种情况下,它也有点违背了服务的意义,即成为共享状态的来源。

    3. 我创建服务的一般模式是将我想要使用的所有内容绑定到一个对象(数据和函数),然后在工厂函数中返回该对象。有时你必须引入一些额外的嵌套,这样 Javascript 原型继承才不会惹恼你(再看一次观察深度的事情),但这是一般的想法。

    您设置的示例服务:

    angular.factory('shareAndUpdate', ['dependencyInjection', function(dependency) {
        var srvc = {};
        srvc.sharedVar = 'something';
        srvc.updateViaHttp = function(){ something };
        return srvc;
    }]);
    

    【讨论】:

    • 只要 updateViaHttp 不返回对象,您给出的示例似乎就可以工作。如果是这样,我分配 srvc.sharedVar = returnedObj 它作为参考。这是真的吗?
    • 您完全可以在服务中拥有嵌套对象,唯一的诀窍是您必须小心查看该值的方式。我在那里的关于手表深度的链接更多地讨论了它,但基本上当你更改属性而不是对象时你可能会遇到问题,因为这样对象就不会将自己标记为“已更改”。同样,您必须注意如何查看服务的属性,请参阅:stsc3000.github.io/blog/2013/10/26/… 服务只是整个应用程序使用的单例对象
    • 无法让它工作,我改变了工厂状态丢失的视图。它不是持久的
    • 你在哪里声明服务?你是如何将它注入你的观点的?这里可能会发生很多事情,因此您可能值得阅读官方 Angular 服务文档以确保您选中了所有框:docs.angularjs.org/guide/services
    【解决方案2】:

    工厂 vs 服务 vs 供应商 - 唯一的区别与依赖注入器如何向您提供它们的实例有关。服务是专门为提供单例而设计的,但只是对添加单例特定功能的工厂的包装。没有什么能阻止你从工厂退回单身人士。

    使用服务来共享状态 - 您需要一个单例,而服务可以轻松定义和注入单例。

    SomeService:
        var foo = {
            bar = 'a'; 
        };
        function getFoo() {
            return foo; 
        }
    
    SomeController[SomeService injected here] :
        $scope.foo = SomeService.getFoo();
        $scope.$watch('foo.bar', ...);
        $scope.setFooBar = function(val) {
            $scope.foo.bar = val;
        };
    
    <a href="" ng-click="setFooBar('2')">2</a>
    

    这里的一般模式是从不做 $scope.foo = { bar: 'Some other reference' }; 因为当你覆盖它时,所有其他依赖于 SomeService 的东西不会获得新的引用 - “臭名昭著的”always use a "dot" in $scope stuff issue

    【讨论】:

      【解决方案3】:

      您可能正在寻找类似 pubsub 服务的东西:

      https://www.npmjs.com/package/angular-pubsub

      但是,根据我的经验,通过适当的设计,您可以最大限度地减少在非嵌套控制器之间共享数据的必要性。

      但有时,对于登录凭据、权限等涵盖所有应用程序的内容,这是不可避免的。在这种情况下,您可以使用服务在控制器之间共享/获取状态,或者您可以使用成熟的 pubsub 机制。

      1. 工厂只是指定服务的另一种方式。调用工厂时,会提供服务实例。您可以将此服务用于您想要的一切,其中之一是在您的控制器之间共享状态。

      2. 您可以通过多种方式查看共享变量,最简单的是继承范围,但是,正如您所提到的,有时您的控制器不一定继承它们的范围。然后,您可以使用 pubsub 服务或仅在两个控制器的共享范围上广播事件(例如 $rootScope,它是您应用的所有控制器范围的父级)。

      3. 1234563但是,如果您以控制器从共享范围继承变量的方式设计应用程序,则可以避免这种情况。然后他们将使用正常的角度机制自动更新他们的东西。遗憾的是,这并不总是能够实现,剩下的就是必须实现一个 pubsub 服务。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-15
        • 2014-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-28
        • 2014-12-14
        相关资源
        最近更新 更多