我有两个控制器,我想在两者之间共享数据。一个控制器支持带有表格的视图,该表格经常更改它所选择的项目"另一个使用所述项目信息从API获取数据。由于这两个控制器支持视图并且位于同一页面上,因此它们不具有经典的父/子层次结构,而是更多的兄弟姐妹'。
目前,我使用简单的事件总线'使用我在两个控制器中注入的$emit
调用根作用域上的事件的服务,其中一个用$rootScope.$on
监听更改。现在我多次听说这是一个糟糕的解决方案,我应该使用服务来共享数据,但是没有人真正解释如何才能看到数据的变化同时
$watch
不好$broadcast
不好(似乎真的要在SO上开战,哪个解决方案应该更加避免)。
我目前的解决方案:
export class Controller1 {
private eventBus : Components.IEventBusService;
constructor(eventBus: Components.IEventBusService) {
this.eventBus = eventBus;
}
void itemSelected(item : IItemModel) {
this.eventBus.emit("itemSelected", { "item" : item });
}
}
export class Controller2 {
constructor($scope : ng.IScope,
eventBus : Components.IEventBusService) {
eventBus.on("itemSelected", (event, data) =>
this.onItemSelected(data), $scope);
}
private onItemSelected(data: any) {
// do something with data.item!
}
}
export interface IEventBusService {
on(event, callback, scope): void;
emit(event, data): void;
}
class EventBusService implements IEventBusService {
private rootScope: ng.IRootScopeService;
constructor($rootScope: ng.IRootScopeService) {
this.rootScope = $rootScope;
}
on(event, callback, scope) : void {
var unbind = this.rootScope.$on(event, callback);
if(scope) {
scope.$on("$destroy", unbind);
}
}
emit(event, data) : void {
data = data || {};
this.rootScope.$emit(event, data);
}
}
使用此解决方案有任何重大缺点吗?是' 服务方式'更好地更新数据等?
答案 0 :(得分:2)
你是对的,应该避免$on
和$emit
,因为它们会产生不必要的噪音。对于这种情况,实际上是一个非常简单的解决方案,我使用它很多。
您需要拥有的是服务中的对象,并为一个控制器提供对它的引用,而另一个需要触发操作的对象可以观察服务变量(顺便说一下,对TypeScript的好工作):
class ItemSelectionWrapper { //just a wrapper, you could have other variables in here if you want
itemSelected: IItemModel;
}
class EventBusService implements IEventBusService {
private myObj: ItemSelectionWrapper;
...
}
然后在你的范围内有itemSelected的控制器中(让我们假设控制器1)你引用相同的变量:
export class Controller1 {
private eventBus : Components.IEventBusService;
constructor(eventBus: Components.IEventBusService) {
this.eventBus = eventBus;
this.eventBus.myObj = this.eventBus.myObj || {};
this.eventBus.myObj.itemSelected = $scope.itemSelected;
}
}
现在,由于在Controller 2中您已注入服务,因此您将观看服务的变量:
$scope.$watch(function(){
return busService.myObj,itemSelected;
}, function (newValue) {
//do what you need
});
答案 1 :(得分:0)
是服务方式'更好地更新数据等?
是。原因是事件就像是在空中扔球并希望有人抓住它并且#34;。而服务是关于两个控制器如何交互的定义合同。
如果您使用TypeScript,您显然关心Type Safety,服务可以为您提供。
仅供参考我们内部有以下指导:
当屏幕与各种占位符高度嵌套时,使用自己的" html + controller"我们需要一种在这些控制器之间共享信息(单一事实来源)的方法。
该部分的主控制器。负责在范围上公开SharedClass实例(允许嵌套的html段直接访问此模型)和任何顶级控制器函数。
角度服务,因为它可以轻松注入单个控制器/指令。包含在屏幕的各个部分中共享的信息/功能,例如多选模式,显示/选择的对象,变异这些对象的操作等。
这些子控制器可以使用简单的Angular Dependency Injection请求SharedClass。 Controller HTML应该自动访问SharedClass实例(因为RootController将其暴露给范围)。