angular/typescript - 我如何从 url 内部数组中获取项目列表
angular/typescript - how can i get a list of items from an url inside array
我正在研究 SWAPI API 和 angular,我想知道如何获得 html 上的星舰名称列表。我可以从 api 和 URL 列表中获取人名列表,但星舰在数组中的 url 中。我怎样才能访问它们?
我有一个 stackblitz link 一些工作:
https://stackblitz.com/edit/angular-ivy-3cqfsb?file=src/app/app.component.html
通过在模板中使用 async
管道,我们可以像这样在模板中完成大部分工作:
<div *ngIf="data$ | async as data">
<div class="boxes">
<div class="box" *ngFor="let person of data.results">
<p>
<strong>name: </strong>
<br />
{{ person.name }}
</p>
<p><strong>Starships:</strong></p>
<ul>
<li *ngFor="let ship of person.starships">{{ ship.name }}</li>
</ul>
</div>
</div>
<div class="buttons">
<button name="previous" (click)="pagination(data.previous)">
previous
</button>
<button name="next" (click)="pagination(data.next)">next</button>
</div>
</div>
接下来您将使用组件作为中间人在模板和服务之间进行通信:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
// Using a template pipe, unsubscribe will happen automatically
data$ = this.peopleService.data$;
constructor(private peopleService: peopleService) {}
pagination(url: string) {
this.peopleService.go(url);
}
}
接下来在服务中我们定义一个 data
行为主体,它将包含要加载的初始 url。
我创建了两个 observables ships$
和 person$
两个 observables ships$
和 person$
将通过每个人并将那个人传递给 ships$
.
@Injectable({ providedIn: 'root' })
export class peopleService {
private readonly rootURL = 'https://swapi.dev/api/people/';
ships$ = (person: Person) =>
of(person.starships).pipe(
// Since i is an array each item will be returned to the next function
concatMap((i: string[]) => i),
// i is now a string from the previous function
concatMap((i) => this.http.get(i)),
// Once all urls complete convert the result back to an array
toArray<Starship>(),
// Replace the string version of the array with the object version
tap((i) => (person.starships = i)),
// Pass person on to the next function
map(() => person)
);
people$ = (people: Person[]) =>
of(people).pipe(
// Read each array item as a string and pass it to the next function
concatMap((i) => i),
// i is now a Person object we will pass it to ships
concatMap((i) => this.ships$(i)),
// convert the results back to an array
toArray()
);
data = new BehaviorSubject<string>(this.rootURL);
data$ = this.data.pipe(
// Process the value of the behavior subject
concatMap((url) => this.http.get<Results>(url)),
concatMap((result) =>
// Send the results to the people func for processing
this.people$(result.results).pipe(
// Map back to the original with strings replace by objects
map<any, Results<Starship>>(() => <Results<Starship>>result)
)
)
);
constructor(private http: HttpClient) { }
go(url?: string) {
// This will trigger the `data` pipe to run again
this.data.next(url || this.rootURL);
}
}
这里有一些使用的例子 interfaces
:
interface Results<T = string | Starship> {
next: string;
previous: string;
results: Person<T>[];
}
interface Person<T = string | Starship> {
name: string;
starships: T[];
}
interface Starship {
name: string;
}
工作示例:https://stackblitz.com/edit/Whosebug-starwars-http
我正在研究 SWAPI API 和 angular,我想知道如何获得 html 上的星舰名称列表。我可以从 api 和 URL 列表中获取人名列表,但星舰在数组中的 url 中。我怎样才能访问它们?
我有一个 stackblitz link 一些工作:
https://stackblitz.com/edit/angular-ivy-3cqfsb?file=src/app/app.component.html
通过在模板中使用 async
管道,我们可以像这样在模板中完成大部分工作:
<div *ngIf="data$ | async as data">
<div class="boxes">
<div class="box" *ngFor="let person of data.results">
<p>
<strong>name: </strong>
<br />
{{ person.name }}
</p>
<p><strong>Starships:</strong></p>
<ul>
<li *ngFor="let ship of person.starships">{{ ship.name }}</li>
</ul>
</div>
</div>
<div class="buttons">
<button name="previous" (click)="pagination(data.previous)">
previous
</button>
<button name="next" (click)="pagination(data.next)">next</button>
</div>
</div>
接下来您将使用组件作为中间人在模板和服务之间进行通信:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
// Using a template pipe, unsubscribe will happen automatically
data$ = this.peopleService.data$;
constructor(private peopleService: peopleService) {}
pagination(url: string) {
this.peopleService.go(url);
}
}
接下来在服务中我们定义一个 data
行为主体,它将包含要加载的初始 url。
我创建了两个 observables ships$
和 person$
两个 observables ships$
和 person$
将通过每个人并将那个人传递给 ships$
.
@Injectable({ providedIn: 'root' })
export class peopleService {
private readonly rootURL = 'https://swapi.dev/api/people/';
ships$ = (person: Person) =>
of(person.starships).pipe(
// Since i is an array each item will be returned to the next function
concatMap((i: string[]) => i),
// i is now a string from the previous function
concatMap((i) => this.http.get(i)),
// Once all urls complete convert the result back to an array
toArray<Starship>(),
// Replace the string version of the array with the object version
tap((i) => (person.starships = i)),
// Pass person on to the next function
map(() => person)
);
people$ = (people: Person[]) =>
of(people).pipe(
// Read each array item as a string and pass it to the next function
concatMap((i) => i),
// i is now a Person object we will pass it to ships
concatMap((i) => this.ships$(i)),
// convert the results back to an array
toArray()
);
data = new BehaviorSubject<string>(this.rootURL);
data$ = this.data.pipe(
// Process the value of the behavior subject
concatMap((url) => this.http.get<Results>(url)),
concatMap((result) =>
// Send the results to the people func for processing
this.people$(result.results).pipe(
// Map back to the original with strings replace by objects
map<any, Results<Starship>>(() => <Results<Starship>>result)
)
)
);
constructor(private http: HttpClient) { }
go(url?: string) {
// This will trigger the `data` pipe to run again
this.data.next(url || this.rootURL);
}
}
这里有一些使用的例子 interfaces
:
interface Results<T = string | Starship> {
next: string;
previous: string;
results: Person<T>[];
}
interface Person<T = string | Starship> {
name: string;
starships: T[];
}
interface Starship {
name: string;
}
工作示例:https://stackblitz.com/edit/Whosebug-starwars-http