2015-05-14 148 views
3

关于控制器之间的共享状态。我很难找到权利的方式来解决SO上推荐的所有可能的解决方案。我用这个草图来说明我到目前为止使用工厂的基本想法。控制器之间的共享状态 - angularjs

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

控制器Ctrl1, Ctrl2, Ctrl3想要始终访问更新版本。他们也可以致电updateViaHttp

factory-controller-communication

  1. 那是一个工厂权目的是什么? (一般的共享状态, 具体到像服务提供商和其他选项)

  2. 如果是这样,腕表以适当的方式如何改变sharedVar? (由 参考对象,$手表,事件(广播,上),...)

  3. 是否有行之有效为对象,数组和 元一个一般模式

回答

1
  1. 你有正确的基本理念,以“工厂”你的意思是“服务”假设 - 它是一种混乱的,我知道,因为服务是使用工厂函数声明。也就是说,这是一个重要的区别,以便您可以更轻松地查找文档等。

  2. 通过使用对象引用和注意watch depths in Angular(我的首选方法)或通过显式注册$观看报表(仍然要小心观看深度)。一般来说,我认为你不应该滥用广播,因为它会让你的代码变得有点混乱。在这种情况下,它也有点违背服务的要点,这是共享状态的来源。

  3. 我创建服务的一般模式是将我想使用的所有东西都绑定到对象(数据和函数),然后在工厂函数中返回该对象。有时你必须引入一些额外的嵌套,以便Javascript原型继承不会与你混淆(再次参见手表的深度),但这是一般想法。

为您建立一个例子服务:

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

您给出的示例似乎只要updateViaHttp不返回对象就会工作。如果是这样,我分配srvc.sharedVar = returnedObj它包含参考。真的吗? – Stefan

+0

你完全可以在服务中嵌套对象,唯一的窍门是你必须小心你如何看待这个值。我在那里关于监视深度的链接更多地讨论了这个问题,但基本上,当您更改属性而不是对象时,可能会遇到问题,因为该对象不会将自己标记为“已更改”。同样,您必须小心如何观看服务的属性,请参阅:http://stsc3000.github.io/blog/2013/10/26/a-tale-of-frankenstein-and-binding-to-service -values-in-angular-dot-js/Services只是你的整个应用程序使用的单例对象 –

+0

无法让它工作,它改变了视图工厂状态丢失。其不持久 – Stefan

1

您可能正在寻找的东西像一个发布订阅服务:

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

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

虽然有时它是不可避免的,但对于像登录凭据,权限,东西等全是应用程序的东西。在这种情况下,您可以使用服务来确实共享/获取控制器之间的状态,或者您可以使用完整的pubsub机制。

  1. 工厂只是指定服务的另一种方式。工厂在被调用时会提供一个服务实例。这项服务可以用于你想要的任何事情,其中​​之一就是在你的控制器之间共享状态。

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

  3. 如果您要使用现有的pubsubservice,它仍然取决于您的实施控制器,以实际执行订阅并观察特定变量并相应地更新其相应的范围。但是,如果您设计的应用程序的方式使您的控制器从共享作用域继承变量,则可以避免这种情况。然后他们会使用正常的角度机制自动更新他们的东西。不幸的是,这并不总是能够实现的,然后你所要做的就是实现一个pubsub服务。

1

工厂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

相关问题