使用服务更新 2 个控制器之间的共享数据
Update shared data between 2 controllers with services
我有 2 个控制器,我想在它们之间共享数据。一个控制器支持 table 的视图,该视图经常更改它的 "selected item",另一个控制器使用所述项目信息从 API 获取数据。由于这两个控制器支持视图并且位于同一页面上,因此它们没有经典的 parent/child 层次结构,而是更 'siblings'.
目前,我正在使用一个简单的 'event bus' 服务,该服务使用 $emit
在根作用域上调用一个事件,我将其注入到两个控制器中,其中一个使用 [=14 监听变化=].现在我多次听说这是一个糟糕的解决方案,我应该使用服务来共享数据,但是没有人真正解释如何在还[=17=时观察数据的变化 ]
- 使用
$watch
不好
$broadcast
不好
(SO 上似乎确实存在 war 应该避免使用哪种解决方案)。
我目前的解决方案:
控制器 1
export class Controller1 {
private eventBus : Components.IEventBusService;
constructor(eventBus: Components.IEventBusService) {
this.eventBus = eventBus;
}
void itemSelected(item : IItemModel) {
this.eventBus.emit("itemSelected", { "item" : item });
}
}
控制器 2
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);
}
}
使用这个解决方案有什么主要缺点吗?关于更新数据等,“服务方式”是否更好?
你是对的,应该避免使用 $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
});
Is 'the service way' better regarding to updating data etc?
是的。原因是事件就像 "throw a ball in the air and hope someone catches it"。而服务是关于两个控制器如何交互的定义契约。
如果您使用 TypeScript,您显然很关心类型安全,服务可以为您提供这一点。
仅供参考,我们有以下内部指导:
控制器之间的共享信息
当屏幕与各种占位符高度嵌套时 "html + controller" 我们需要一种在这些控制器之间共享信息(单一真实来源)的方法。
1 个根控制器
该部分的主控制器。负责在范围内公开 SharedClass 实例(允许嵌套 html 段直接访问此模型)和任何顶级控制器功能。
2 个共享类
一个 angular 服务,因为它很容易注入到单独的控制器/指令中。包含在屏幕的各个部分共享的信息/功能,例如多select模式,显示/selected对象,改变这些对象的操作等
3 个人 Html + 控制者
这些子控制器可以使用简单的 Angular 依赖注入请求 SharedClass。 Controller HTML 应该自动获得对 SharedClass 实例的访问权限(因为 RootController 将其暴露给范围)。
我有 2 个控制器,我想在它们之间共享数据。一个控制器支持 table 的视图,该视图经常更改它的 "selected item",另一个控制器使用所述项目信息从 API 获取数据。由于这两个控制器支持视图并且位于同一页面上,因此它们没有经典的 parent/child 层次结构,而是更 'siblings'.
目前,我正在使用一个简单的 'event bus' 服务,该服务使用 $emit
在根作用域上调用一个事件,我将其注入到两个控制器中,其中一个使用 [=14 监听变化=].现在我多次听说这是一个糟糕的解决方案,我应该使用服务来共享数据,但是没有人真正解释如何在还[=17=时观察数据的变化 ]
- 使用
$watch
不好 $broadcast
不好
(SO 上似乎确实存在 war 应该避免使用哪种解决方案)。
我目前的解决方案:
控制器 1
export class Controller1 {
private eventBus : Components.IEventBusService;
constructor(eventBus: Components.IEventBusService) {
this.eventBus = eventBus;
}
void itemSelected(item : IItemModel) {
this.eventBus.emit("itemSelected", { "item" : item });
}
}
控制器 2
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);
}
}
使用这个解决方案有什么主要缺点吗?关于更新数据等,“服务方式”是否更好?
你是对的,应该避免使用 $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
});
Is 'the service way' better regarding to updating data etc?
是的。原因是事件就像 "throw a ball in the air and hope someone catches it"。而服务是关于两个控制器如何交互的定义契约。
如果您使用 TypeScript,您显然很关心类型安全,服务可以为您提供这一点。
仅供参考,我们有以下内部指导:
控制器之间的共享信息
当屏幕与各种占位符高度嵌套时 "html + controller" 我们需要一种在这些控制器之间共享信息(单一真实来源)的方法。
1 个根控制器
该部分的主控制器。负责在范围内公开 SharedClass 实例(允许嵌套 html 段直接访问此模型)和任何顶级控制器功能。
2 个共享类
一个 angular 服务,因为它很容易注入到单独的控制器/指令中。包含在屏幕的各个部分共享的信息/功能,例如多select模式,显示/selected对象,改变这些对象的操作等
3 个人 Html + 控制者
这些子控制器可以使用简单的 Angular 依赖注入请求 SharedClass。 Controller HTML 应该自动获得对 SharedClass 实例的访问权限(因为 RootController 将其暴露给范围)。