Angular 使用 BehaviorSubject 异步管道扩展组件不工作
Angular extend component with BehaviorSubject async pipe not working
我似乎无法从子组件触发父组件的异步管道来更新视图。
这听起来可能有点令人困惑,但让我尝试通过显示我的代码的简化版本来解释。
如果有一个 class 被另一个 class 扩展。
export class ParentComponent implements OnInit{
protected subject$: BehaviorSubject<string[]>;
ngOnInit() {
this.subject$ = new BehaviorSubject<string[]>([]);
}
}
模板如下:
<span *ngFor="let niceString of subject$ | async">
{{niceString}}
</span>
扩展:
export class ChildComponent extends ParentComponent implements OnInit{
ngOnInit() {
super.ngOnInit();
this.subject$.next(['string1', 'string2']);
}
}
模板未在浏览器中更新。
如果我在父组件中调用带有 subject$.next 的行,它将按预期更新并在浏览器中显示两个字符串。
所以我尝试通过延迟 3 秒调用 SetTimeOut 来玩弄它,看看它是否以某种方式被快速调用。这并没有解决问题。我还在父函数中添加了 subject$.next ,然后我从子函数中调用了这个函数,这也无法解决它。但是如果我在父 class 中调用相同的新函数,视图会按预期更新。
我还在父级中添加了一个自定义订阅,它像这样收听 subject$:
protected subjectSubscription: Subscription;
this.subjectSubscription = this.subject$.pipe(take(2)).subscribe((justChecking: string[]) => {
debugger;
});
这将按预期触发,但浏览器中的视图未更新为值 'string1'、'string2'。
我是不是遗漏了什么?
(编辑)添加 StackBlitz:https://stackblitz.com/edit/angular-tt65ig
生命周期方法不会被继承,因此使您的 ChildComponent
的 ngOnInit()
方法调用无用。
虽然我更希望您使用服务设计模式,但要以您可以使用的方式做到这一点 super.ngOnInit()
。
我无法重现所描述的行为。在这里进行一次有效的 stackblitz:https://stackblitz.com/edit/angular-gfxqpe
您是否希望 parent 的模板被 child 使用?那行不通的。您可以引用相同的 html 文件,如
@Component({
selector: 'app-child',
templateUrl: '../parent/parent.component.html',
styleUrls: ['./child.component.css']
})
您正在混合继承和组合:
- 子组件是一个父组件,因为它扩展了Parent
- 子组件有一个父组件,因为子组件的模板包含
<app-parent>
.
因此您正在创建父组件的两个实例:
- 一个通过在根组件模板中使用
<app-child>
。这个父实例是子实例。它的主题发出两个字符串,但它的模板只有 <app-parent>
从不显示这两个字符串。
一个通过在子组件模板中使用 <app-parent>
。这个父实例不是子实例。它的模板显示它的主题的内容,但它的主题从不发出任何东西,因为它不是子组件的实例,只有子组件包含发出 2 个字符串的代码。
parent
- has subject1
^
-
|
|
extends
|
| displays
child --------------------------------> parent
- emits from subject1 - has subject2
- displays content of subject2
如何解决?不要那样做。要么使用继承,要么最好使用组合,但不要将两者混用。
我似乎无法从子组件触发父组件的异步管道来更新视图。 这听起来可能有点令人困惑,但让我尝试通过显示我的代码的简化版本来解释。
如果有一个 class 被另一个 class 扩展。
export class ParentComponent implements OnInit{
protected subject$: BehaviorSubject<string[]>;
ngOnInit() {
this.subject$ = new BehaviorSubject<string[]>([]);
}
}
模板如下:
<span *ngFor="let niceString of subject$ | async">
{{niceString}}
</span>
扩展:
export class ChildComponent extends ParentComponent implements OnInit{
ngOnInit() {
super.ngOnInit();
this.subject$.next(['string1', 'string2']);
}
}
模板未在浏览器中更新。 如果我在父组件中调用带有 subject$.next 的行,它将按预期更新并在浏览器中显示两个字符串。
所以我尝试通过延迟 3 秒调用 SetTimeOut 来玩弄它,看看它是否以某种方式被快速调用。这并没有解决问题。我还在父函数中添加了 subject$.next ,然后我从子函数中调用了这个函数,这也无法解决它。但是如果我在父 class 中调用相同的新函数,视图会按预期更新。
我还在父级中添加了一个自定义订阅,它像这样收听 subject$:
protected subjectSubscription: Subscription;
this.subjectSubscription = this.subject$.pipe(take(2)).subscribe((justChecking: string[]) => {
debugger;
});
这将按预期触发,但浏览器中的视图未更新为值 'string1'、'string2'。
我是不是遗漏了什么?
(编辑)添加 StackBlitz:https://stackblitz.com/edit/angular-tt65ig
生命周期方法不会被继承,因此使您的 ChildComponent
的 ngOnInit()
方法调用无用。
虽然我更希望您使用服务设计模式,但要以您可以使用的方式做到这一点 super.ngOnInit()
。
我无法重现所描述的行为。在这里进行一次有效的 stackblitz:https://stackblitz.com/edit/angular-gfxqpe
您是否希望 parent 的模板被 child 使用?那行不通的。您可以引用相同的 html 文件,如
@Component({
selector: 'app-child',
templateUrl: '../parent/parent.component.html',
styleUrls: ['./child.component.css']
})
您正在混合继承和组合:
- 子组件是一个父组件,因为它扩展了Parent
- 子组件有一个父组件,因为子组件的模板包含
<app-parent>
.
因此您正在创建父组件的两个实例:
- 一个通过在根组件模板中使用
<app-child>
。这个父实例是子实例。它的主题发出两个字符串,但它的模板只有<app-parent>
从不显示这两个字符串。 一个通过在子组件模板中使用
<app-parent>
。这个父实例不是子实例。它的模板显示它的主题的内容,但它的主题从不发出任何东西,因为它不是子组件的实例,只有子组件包含发出 2 个字符串的代码。parent - has subject1 ^ - | | extends | | displays child --------------------------------> parent - emits from subject1 - has subject2 - displays content of subject2
如何解决?不要那样做。要么使用继承,要么最好使用组合,但不要将两者混用。