2

我似乎无法从子组件触发父组件的异步管道来更新视图。这可能听起来有点令人困惑,但让我尝试通过显示我的代码的简化版本来解释。

如果有一个由另一个类扩展的类。

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 添加到父级的函数中,然后从子级调用该函数,这也无法解决。但是,如果我在父类中调用相同的新函数,则视图会按预期更新。

我还在父级中添加了一个自定义订阅,它像这样监听主题 $:

protected subjectSubscription: Subscription;

this.subjectSubscription = this.subject$.pipe(take(2)).subscribe((justChecking: string[]) => {
    debugger;
});

这将按预期触发,但浏览器中的视图未使用值“string1”、“string2”更新。

我在这里错过了什么吗?

(编辑)添加 StackBlitz:https ://stackblitz.com/edit/angular-tt65ig

4

3 回答 3

3

您正在混合继承和组合:

  • 子组件父组件,因为它扩展了 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
    

怎么修?不要那样做。要么使用继承,要么最好使用组合,但不要混合使用两者。

于 2019-12-02T16:26:25.473 回答
1

我无法重现所描述的行为。在这里有一个有效的堆栈闪电战: https ://stackblitz.com/edit/angular-gfxqpe

您是否希望孩子使用父母的模板?那是行不通的。您可以引用相同的 html 文件,例如

@Component({
  selector: 'app-child',
  templateUrl: '../parent/parent.component.html',
  styleUrls: ['./child.component.css']
})
于 2019-12-01T09:06:28.327 回答
-1

Lifecycle methods are not inherited therefore rendering your ChildComponent's ngOnInit() method call useless.

Though I would much prefer you use a service design pattern, to do this the way you have things you could use super.ngOnInit().

于 2019-12-01T08:31:55.133 回答