使用服务更新 2 个控制器之间的共享数据

Update shared data between 2 controllers with services

我有 2 个控制器,我想在它们之间共享数据。一个控制器支持 table 的视图,该视图经常更改它的 "selected item",另一个控制器使用所述项目信息从 API 获取数据。由于这两个控制器支持视图并且位于同一页面上,因此它们没有经典的 parent/child 层次结构,而是更 'siblings'.

目前,我正在使用一个简单的 'event bus' 服务,该服务使用 $emit 在根作用域上调用一个事件,我将其注入到两个控制器中,其中一个使用 [=14 监听变化=].现在我多次听说这是一个糟糕的解决方案,我应该使用服务来共享数据,但是没有人真正解释如何在还[=17=时观察数据的变化 ]

(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 将其暴露给范围)。