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

Javascript 从另一个对象注册对象的属性更改,javascript,typescript,design-patterns,es6-proxy,Javascript,Typescript,Design Patterns,Es6 Proxy,在我的项目中,我有一个widgetBar,它可以包含一个或多个小部件 单击widgetBar中的小部件图标时,会打开一个面板,显示所按下的小部件的内容(类似于带有所有下拉菜单的导航栏) 每个widget都是一个类,它有一个togglePanel()方法,绑定到widget图标上的onlcick事件并打开/关闭面板。此方法还将小部件的isActive属性设置为true(当面板打开时)或false(当面板关闭时) WidgetBar构造函数将widgets的列表作为参数,该参数将成为其this.wi

在我的项目中,我有一个
widgetBar
,它可以包含一个或多个
小部件

单击widgetBar中的小部件图标时,会打开一个面板,显示所按下的小部件的内容(类似于带有所有下拉菜单的导航栏)

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

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

class WidgetBar {
    private widgets: Widget[];

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

    getWidgets() {
        return this.widgets;
    }
}
(我的项目)规则是,每当一个小部件打开它的面板时,所有其他面板都应该关闭

如何从
WidgetBar
自动检查其
小部件
s是否更改了其
isActive
属性,以便确保每次打开的面板不超过一个

我读过,但我不确定这是否能帮助我解决这个问题

编辑 那怎么办


小部件的
属性设置为可观察的
isActive
类,并从
WidgetBar
订阅以侦听任何更新是否是一个好主意,如中所述?

您可以在小部件打开时使用它们。小部件栏的工作是执行“规则”。当它获得一个新的open事件时,您可以让它在所有其他子窗口小部件上调用close(通过ViewChild/viewchilds)


或者,您可以将逻辑移出组件,并拥有一个负责所有逻辑的服务。该服务可以通过rxjs订阅将小部件及其属性(如活动)公开到小部件栏。

打开小部件时,您可以拥有这些小部件。小部件栏的工作是执行“规则”。当它获得一个新的open事件时,您可以让它在所有其他子窗口小部件上调用close(通过ViewChild/viewchilds)


或者,您可以将逻辑移出组件,并拥有一个负责所有逻辑的服务。该服务可以通过rxjs订阅将小部件及其属性(如活动)公开到小部件栏。

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

我所做的是创建一个新属性this.widgetActivated$=newsubject(){id:currentWidget.id,isActive:currentWidget.isActive}
的对象来填充代码>调用
.next()
。然后我订阅它,并在其他处于活动状态且具有不同id的小部件上调用
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};
    }

}
接口状态{
id:字符串;
isActive:布尔型;
}
WidgetBar类{
私有小部件:小部件[];
私有widgetActivated$:Subject;//重要更改
构造函数(小部件:小部件[]){
this.widgetActivated$=new Subject();//重要更改
this.widgets=widgets;
}
getWidgets(){
返回这个.widgets;
}
私有widgetHandler(小部件:小部件){
fromEvent(widget.widgetBox,'click')。订阅(
()=>this.toggleWidgetPanel(小部件)
);
此.widgetActivated$.subscribe(状态=>{
const widgetsToClose=this.getWidgets().filter(widget=>
widget.isActive==true&&widget.id!==status.id);
如果(widgetsToClose){
forEach(widgetToClose=>this.closePanel(widgetToClose));
}
})
}
私有切换WidgetPanel(小部件:小部件){
如果(!widget.getPanel().classList.contains(“活动”)){
这个.openPanel(小部件);
}否则{
这个.closePanel(小部件);
}
}
私有openPanel(小部件:小部件){
getPanel().classList.add(“活动”);
widget.isActive=true;
this.widgetActivated$.next(this.getWidgetStatus(小部件));//重要更改
}
专用关闭面板(小部件:小部件){
widget.getPanel().classList.remove(“活动”);
}
私有getWidgetStatus(widget:widget):widgetStatus{
返回{id:widget.id,isActive:widget.isActive};
}
}

我还转换了
this.element.onclick=this.togglePanel.bind(this)从事件(widget.widgetBox,'click')中
订阅(()=>this.toggleWidgetPanel(widget))因为我觉得它更具可读性,并且它没有带来很多关于
这个arg
上下文的问题(请参阅)。

这对我来说有点棘手,但最后我用它解决了我的问题

我所做的是创建一个新属性this.widgetActivated$=newsubject(){id:currentWidget.id,isActive:currentWidget.isActive}
的对象来填充代码>调用
.next()
。然后我订阅它,并在其他处于活动状态且具有不同id的小部件上调用
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};
    }

}
接口状态{
id:字符串;
isActive:布尔型;
}
WidgetBar类{
私有小部件:小部件[];
私有widgetActivated$:Subject;//重要更改
构造函数(小部件:小部件[]){
this.widgetActivated$=new Subject();//重要更改
this.widgets=widgets;
}
getWidgets(){
返回这个.widgets;
}
私有widgetHandler(小部件:小部件){
fromEvent(widget.widgetBox,'click')。订阅(
()=>this.toggleWidgetPanel(小部件)
);
此.widgetActivated$.subscribe(状态=>{
const widgetsToClose=this.getWidgets().filter(widget=>