【问题标题】:Observable input is null in child component. Why?子组件中的可观察输入为空。为什么?
【发布时间】:2021-03-16 16:34:00
【问题描述】:

我正面临着我不理解的情况。我有一个父组件(示例中为 app.component),它从 API 获取其数据作为可观察对象

然后使用异步管道将这些数据传递给子 (hello.component)。

然后那个孩子接收输入,但是当 ngOnInit 在孩子中运行时,输入是null

我不明白为什么,也不知道如何使输入成为 API 的实际返回值。 app.component 中对detectChanges() 的调用是触发子项更改检测的绝望尝试,但这不会重新运行ngOnInit,所以它有点没有实际意义。我把它留在那里是因为这就是我正在使用的实际代码的样子。

我知道这段代码很糟糕。不是我写的。不幸的是,我正在使用的组件就是这样,我无法重构它,因为你猜对了,没有单元测试。我正在努力清理它,但现在我必须按原样重用该组件。

Stackblitz:https://stackblitz.com/edit/angular-ivy-rw1xte?devtoolsheight=33&file=src/app/hello.component.ts

// app.component.ts
import { ChangeDetectorRef, Component, VERSION } from "@angular/core";
import { interval, Observable, of } from "rxjs";
import { mapTo, tap } from "rxjs/operators";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  public name$: Observable<any> = of({});

  constructor(private cdRef: ChangeDetectorRef) {}

  public ngOnInit() {
    this.name$ = interval(3000).pipe(
      mapTo(() => {
        first: "Eunice";
      }),
      tap(() => this.cdRef.detectChanges())
    );
  }
}
<!-- app.component.html -->
<hello [name]="name$ | async"></hello>
<p>
  Start editing to see some magic happen :)
</p>
// hello.component.ts
import { Component, Input } from "@angular/core";

@Component({
  selector: "hello",
  template: `
    <div *ngIf="name">
      <h1>Hello {{ this.name.first }}!</h1>
      <h1>{{ greetings }}</h1>
    </div>
  `,
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class HelloComponent {
  @Input() name: { first?: string }
  public greetings: string = "";
  public firstName: string = "";

  public async ngOnInit() {
    console.log('name:',this.name); // name: null

    if (this.name) {
      // this conditional is always false because this.name is always null
      // and so this never runs.
      console.log("got name");
      this.firstName = this.name.first || "fallback";
      this.greetings = await new Promise(resolve =>
        resolve("how do you do, ${firstName}?")
      );
    }
  }
}

【问题讨论】:

标签: javascript angular rxjs


【解决方案1】:
this.name$ = interval(3000).pipe(
    mapTo({
        first: "Eunice"
    }),
    tap(() => this.cdRef.detectChanges())
);

请像上面那样修复它。 mapTo 不需要接受函数。它没有为你犯错误吗? :)

另外,name 输入是 null,当 hello 组件被挂载时。 您需要检查ngOnChanges 中的名称,或者只有在名称可用时才需要挂载hello 组件。

例如:

<hello *ngIf="name$ | async as name" [name]="name"></hello>

或者

public async ngOnChanges() {
    console.log('name:', this.name); // name: null

    if (this.name) {
        ...
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 2020-07-16
    • 2015-08-11
    相关资源
    最近更新 更多