我正在建立一个像Angular中的黄金布局的面板对接系统。我使用动态创建的组件将面板添加到页面中,如下所示:
@ViewChild('dynamicInsert', {read: ViewContainerRef }) dynamicInsert: ViewContainerRef;
/**
* This is the onChanges for the dock component
*/
ngOnChanges() {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.panelType);
this.dynamicInsert.clear();
this.panelRef = this.dynamicInsert.createComponent(componentFactory);
this.panelRef.location.nativeElement.setAttribute('dock-tree-id', this.dockTreeId);
this.panelRef.location.nativeElement.setAttribute('movable', this.movable);
this.initializePanel(this.panelRef.instance);
}
dockTree是一个对象,用于保存当前打开的不同面板。这样我就能够非常轻松地将当前布局保存到本地存储。
由于目前我的网页上有多个“停靠点”'像这样:
<div #dock
class="dock">
<ng-template #dynamicInsert></ng-template>
</div>
要在这些面板之间进行通信,我正在使用服务。例如,我创建了clickService。一个面板有一个调用click()的按钮,另一个面板调用了getClicks():
@Injectable()
export class ClickService {
private clicks = 0;
private observer;
public getClicks(): Observable<number> {
return new Observable<number>((observer: Observer<number>) => {
this.observer = observer;
observer.next(this.clicks);
});
}
public click() {
this.clicks++;
this.observer.next(this.clicks);
}
}
现在当我点击按钮时,订阅我服务的其他面板应全部更新,但只有最后添加的面板更新:
当我动态添加一个新面板,添加一个新元素并附加面板时,新面板将被订阅,但前一个面板将会中断。将面板拖放到新位置(触发ngOnChanges)时,面板将具有正确的值,但只有最后一个面板将侦听单击。
为什么会这样?
答案 0 :(得分:1)
问题在于,无论何时调用getClicks
,都会使用最新的观察者替换对上一次点击观察者的引用。所以基本上你最多只有一(1)个观察者,与创建的面板数量无关。
private observer;
public getClicks(): Observable<number> {
return new Observable<number>((observer: Observer<number>) => {
this.observer = observer; // replaces the previous observer with the newest
observer.next(this.clicks); // pushes the current counter to the newest observer
});
public click() {
this.clicks++;
this.observer.next(this.clicks); // only the latest observer gets the new state
}
}
我不知道为什么你选择创建一个observable来组播来自独特来源的点击次数,但这可以通过使用主题来简化:
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class ClickService {
private readonly _clicks$ = new BehaviorSubject<number>(0);
readonly clicks$: Observable<number> = this._clicks$.asObservable();
public click() {
this._clicks$.next(this._clicks$.value + 1);
// some would argue that using a sync. value access in a subject is bs
}
}
现在您应该订阅clicks$
流来多播点击次数。