javascript - 子组件中的可观察输入为空。为什么?
问题描述
我面临着一个我不明白的情况。我有一个父组件(示例中为 app.component),它从 API 获取其数据作为可观察对象
然后使用异步管道将此数据传递给子节点(hello.component)。
然后那个孩子接收输入,但是当 ngOnInit 在孩子中运行时,输入是null
.
我不明白为什么,也不知道如何使输入成为 API 的实际返回值。对detectChanges()
in app.component 的调用是触发子项更改检测的绝望尝试,但这不会重新运行 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}?")
);
}
}
}
解决方案
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) {
...
}
}
推荐阅读
- spring-mvc - Spring Reactive 与 Spring MVC + MySQL 的集成
- micronaut - 如果我们有两个带有@MicronautTest 的测试类,那么嵌入式服务器将被启动多少次?
- rest - 如何获取 REST API 多对多对多信息?
- javascript - 将 PWA(渐进式 Web 应用程序)部署到 Firebase 后,如何解决“加载资源失败:服务器响应状态为 404 ()”错误?
- python - 如何在 python 3.7.3 64 位 windows 10 上安装 dlib 时修复错误
- laravel - 使用 Laravel 查询生成器,我需要来自两个表订单和出价的拒绝出价
- dji-sdk - DJI Windows 示例代码 - USB 连接 - 无法查看 FPV
- react-native - 如何使用 React Navigation 根据 React Native 中的 state 属性更改导航标题按钮样式?
- mysql - 字符串集中的 MySQL 更新字符串
- html - 在文本之上显示文本