从另一个对象注册一个对象的属性更改

时间:2020-07-16 13:32:08

标签: javascript typescript design-patterns es6-proxy

在我的项目中,我有一个widgetBar,其中可以包含一个或多个widget

单击widgetBar中的widget图标时,将打开一个面板,以显示按下的widget的内容(带有所有下拉菜单的导航栏的类型)。

每个widget是一个具有togglePanel()方法的类,该方法绑定到小部件图标上的onlcick事件并打开/关闭面板。此方法还将小部件的isActive属性设置为true(当面板打开时)或false(当面板关闭时)。

class Widget {
    isActive: boolean = false;
    element: HTMLElement;
    id: string;

    constructor(id: string) {
        this.id = id;
        this.element = document.crateElement('DIV');
        // ... this.element and other things represent the widget DOM object
        this.element.onclick = this.togglePanel.bind(this);
    }

    togglePanel() {
        if (this.panel.classList.contains('active')) {
            this.openPanel();
            this.isActive = true;
        } else {
            this.closePanel();
            this.isActive = false;
        }
    }
}

WidgetBar构造函数将widget的列表作为参数,成为其this.widgets属性。它还具有getWidgets()方法,可以访问此属性。

class WidgetBar {
    private widgets: Widget[];

    constructor(widgets: Widget[]) {
        this.widgets = widgets;
    }

    getWidgets() {
        return this.widgets;
    }
}

(我的项目的)规则是,每当一个小部件打开其面板时,所有其他面板都应关闭。

如何自动从WidgetBar中检查其widget之一是否更改了其isActive属性,以便确保一次只能打开一个面板? ?

我了解了Proxy,但是我不确定这是否可以帮助我解决此问题。

编辑

Observables呢?

isActive类的Widget属性设置为Observable,并从WidgetBar订阅以侦听任何更新是一个好主意,如this answer中所述?

2 个答案:

答案 0 :(得分:0)

打开小部件emit an event时,您可以使用它们。小部件栏的工作是强制执行“规则”。当它收到新的打开事件时,您可以让它在所有其他子窗口小部件上调用关闭(通过ViewChild / ViewChildren)。

或者,您可以将逻辑移出组件,并拥有负责所有逻辑的服务。该服务可以通过可订阅的rxjs向窗口小部件栏显示窗口小部件及其属性(例如,活动的)。

答案 1 :(得分:0)

这对我来说有点棘手,但最终我用rxjs Subjects解决了我的问题。

我要做的是创建一个新属性not equal 2.9999999999999999e+100 3.0000000000000006e+100 ,每当打开小部件面板时,我都会使用诸如this.widgetActivated$ = new Subject();之类的对象来填充.next()。然后,我订阅它,并在其他处于活动状态且具有不同ID的小部件上调用{id: currentWidget.id, isActive: currentWidget.isActive}

这是更新的代码:

closePanel()

我也将interface widgetStatus { id: string; isActive: boolean; } class WidgetBar { private widgets: Widget[]; private widgetActivated$: Subject<widgetStatus>; // IMPORTANT CHANGE constructor(widgets: Widget[]) { this.widgetActivated$ = new Subject(); // IMPORTANT CHANGE this.widgets = widgets; } getWidgets() { return this.widgets; } private widgetHandler(widget: Widget) { fromEvent(widget.widgetBox, 'click').subscribe( () => this.toggleWidgetPanel(widget) ); this.widgetActivated$.subscribe(status => { const widgetsToClose = this.getWidgets().filter(widget => widget.isActive === true && widget.id !== status.id); if (widgetsToClose) { widgetsToClose.forEach(widgetToClose => this.closePanel(widgetToClose)); } }) } private toggleWidgetPanel(widget: Widget) { if (!widget.getPanel().classList.contains("active")) { this.openPanel(widget); } else { this.closePanel(widget); } } private openPanel(widget: Widget) { widget.getPanel().classList.add("active"); widget.isActive = true; this.widgetActivated$.next(this.getWidgetStatus(widget)); // IMPORTANT CHANGE } private closePanel(widget: Widget) { widget.getPanel().classList.remove("active"); } private getWidgetStatus(widget: Widget): widgetStatus { return {id: widget.id, isActive: widget.isActive}; } } 转换为this.element.onclick = this.togglePanel.bind(this);,因为我觉得它更具可读性,并且没有带来关于fromEvent(widget.widgetBox, 'click').subscribe(() => this.toggleWidgetPanel(widget));上下文的很多问题(请参阅this other question of mine)。