gpt4 book ai didi

angular - 订阅 *ngIf 背后的 DOM 事件

转载 作者:行者123 更新时间:2023-12-05 02:07:25 26 4
gpt4 key购买 nike

我喜欢能够将 DOM 事件作为可观察流处理,调用过滤器、concatMap 等,如下例所示。

@Component({
template: `<button #btn>Submit<button`,
selector: 'app-test',
})
class TestComponent implements AfterViewInit, OnDestroy {

private destroy$ = new Subject<boolean>();

@ViewChild('btn') private btn: ElementRef<HtmlButtonElement>;

constructor(private testService: TestService) { }

ngAfterViewInit() {
fromEvent(btn.nativeElement, 'click').pipe(
exhaustMap(() = > {
return this.testService.save();
}),
takeUntil(this.destroy$),
).subscribe();
}

ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
}

但有时我想从中监听事件的元素在 *ngIf 后面并且在 ngAfterViewInit 运行时不存在。仍然以 react 方式监听事件的最佳方式是什么?

我尝试的一种方法是在检查 ElementRef 是否存在的 if 语句后面的 ngOnViewChecked 中设置与上面相同的订阅,并带有一个标志以避免多个订阅。但我发现那很乱。

这样做是好的做法吗?

@Component({
template: `<button (click)="clickEvent.emit()">Submit<button`,
selector: 'app-test',
})
class TestComponent implements OnInit, OnDestroy {

private destroy$ = new Subject<boolean>();

clickEvent = new EventEmitter<void>();

constructor(private testService: TestService) { }

ngOnInit() {
this.clickEvent.pipe(
exhaustMap(() = > {
return this.testService.save();
}),
takeUntil(this.destroy$),
).subscribe();
}

ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
}

我应该用 Subject 替换 EventEmitter 吗?有没有比这些更好的方法?

编辑:为了清楚起见,我的问题与从由于 *ngIf 而可能不存在的元素订阅事件有关

最佳答案

使用 @ViewChildrenQueryList 来监听 DOM 变化。

import { Component, AfterViewInit, OnDestroy, ElementRef, ViewChildren, QueryList } from '@angular/core';
import { Subject, fromEvent, of } from 'rxjs';
import { exhaustMap, takeUntil, switchMap, map, filter } from 'rxjs/operators';

@Component({
selector: 'app-test',
template: `<button #btn>Submit<button`
})
export class TestComponent implements AfterViewInit, OnDestroy {

private destroy$ = new Subject<boolean>();

// Any time a child element is added, removed, or moved,
// the query list will be updated, and the changes observable
// of the query list will emit a new value.
@ViewChildren('btn') private btn: QueryList<ElementRef>;

constructor(private testService: TestService) { }

ngAfterViewInit() {
this.btn.changes.pipe(
// only emit if there is an element and map to the desired stream
filter((list: QueryList<ElementRef>) => list.length > 0),
switchMap((list: QueryList<ElementRef>) => fromEvent(list.first.nativeElement, 'click')),
// add your other operators
exhaustMap(() => this.testService.save()),
takeUntil(this.destroy$),
).subscribe(console.log);
// Trigger a change event to emit the current state
this.btn.notifyOnChanges()
}

ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
}

https://stackblitz.com/edit/angular-ivy-iklbs9

关于angular - 订阅 *ngIf 背后的 DOM 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61810604/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com