注册一个对象从另一个对象的 属性 变化
Registering property changes of an object from another object
在我的项目中,我有一个 widgetBar
可以包含一个或多个 widget
。
单击 widgetBar 中的小部件图标时,会打开一个面板以显示所按小部件的内容(类似于带有所有下拉菜单的导航栏)。
每个 widget
都是一个 class,它有一个 togglePanel()
方法,该方法绑定到小部件图标和 openes/closes 面板上的 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;
}
}
(我的项目的)规则是,每当一个小部件打开其面板时,所有其他面板都应关闭。
如果其中一个 widget
已更改其 isActive
属性,我如何从 WidgetBar
自动检查,以便我可以确保不超过一个一次打开面板?
我读到了 Proxy
,但我不确定这是否可以帮助我解决这个问题。
编辑
那Observable
s呢?
让 Widget
class 的 isActive
属性 成为 Observable 并从 WidgetBar
订阅以监听任何更新,如 ?
中所述
您可以在打开时获得小部件 emit an event。小部件栏的工作是执行“规则”。当它获得一个新的打开事件时,您可以让它在所有其他子部件上调用关闭(通过 ViewChild/ViewChildren)。
或者,您可以将逻辑移出组件并拥有一个负责所有逻辑的服务。该服务可以通过 rxjs 订阅将小部件及其属性(例如活动)公开到小部件栏。
这对我来说有点棘手,但最后我用 rxjs Subjects
解决了我的问题。
我所做的是创建一个新的 属性 this.widgetActivated$ = new Subject();
,每当打开小部件面板时,我都会使用 {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};
}
}
我还将 this.element.onclick = this.togglePanel.bind(this);
转换为 fromEvent(widget.widgetBox, 'click').subscribe(() => this.toggleWidgetPanel(widget));
,因为我觉得它更具可读性,并且不会带来很多关于 thisArg
上下文的问题(参见 ).
在我的项目中,我有一个 widgetBar
可以包含一个或多个 widget
。
单击 widgetBar 中的小部件图标时,会打开一个面板以显示所按小部件的内容(类似于带有所有下拉菜单的导航栏)。
每个 widget
都是一个 class,它有一个 togglePanel()
方法,该方法绑定到小部件图标和 openes/closes 面板上的 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;
}
}
(我的项目的)规则是,每当一个小部件打开其面板时,所有其他面板都应关闭。
如果其中一个 widget
已更改其 isActive
属性,我如何从 WidgetBar
自动检查,以便我可以确保不超过一个一次打开面板?
我读到了 Proxy
,但我不确定这是否可以帮助我解决这个问题。
编辑
那Observable
s呢?
让 Widget
class 的 isActive
属性 成为 Observable 并从 WidgetBar
订阅以监听任何更新,如
您可以在打开时获得小部件 emit an event。小部件栏的工作是执行“规则”。当它获得一个新的打开事件时,您可以让它在所有其他子部件上调用关闭(通过 ViewChild/ViewChildren)。
或者,您可以将逻辑移出组件并拥有一个负责所有逻辑的服务。该服务可以通过 rxjs 订阅将小部件及其属性(例如活动)公开到小部件栏。
这对我来说有点棘手,但最后我用 rxjs Subjects
解决了我的问题。
我所做的是创建一个新的 属性 this.widgetActivated$ = new Subject();
,每当打开小部件面板时,我都会使用 {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};
}
}
我还将 this.element.onclick = this.togglePanel.bind(this);
转换为 fromEvent(widget.widgetBox, 'click').subscribe(() => this.toggleWidgetPanel(widget));
,因为我觉得它更具可读性,并且不会带来很多关于 thisArg
上下文的问题(参见