我一直在使用 Angular 16、TypeScript 和电影数据库 (TMDB) 开发 SPA。
我需要在其中一个组件上执行“无限滚动”功能。
为此目的,我有:
export class MoviesByGenre {
constructor(
private activatedRoute: ActivatedRoute,
private movieService: MovieService
) { }
public genreName: string | undefined = '';
public movieResponse!: MovieResponse;
public movies: Movie[] | undefined = [];
public genreResponse!: GenreResponse;
public genres: Genre[] | undefined = [];
public getMoviesByGenre(): void {
// Get genre id (from URL parameter)
const genreId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
const maxPage: number = 10;
let pageNumber: number = 1;
let isLoading: boolean = false;
// Get genre name from genres array
this.movieService.getAllMovieGenres().subscribe((response) => {
this.genreResponse = response;
this.genres = this.genreResponse.genres;
if (this.genres && this.genres.length) {
let currentGenre = this.genres.find(genre => genre.id === genreId);
if (currentGenre) {
this.genreName = currentGenre.name || '';
this.movieService.defaultTitle = this.genreName;
}
}
});
// Get movies by genre id
this.movieService.getMoviesByGenre(genreId, pageNumber).subscribe((response) => {
this.movieResponse = response;
this.movies = this.movieResponse.results;
@HostListener('window:scroll', ['$event'])
onWindowScroll(event) {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight &&! isLoading) {
if (pageNumber < maxPage) {
isLoading = true;
// Push into the movies array
this.movies?.push(...this.movies);
// Increment page number
pageNumber++;
isLoading = false;
}
}
}
})
}
ngOnInit() {
this.activatedRoute.params.subscribe(() => {
this.getMoviesByGenre();
});
}
ngOnDestroy() {
this.movieService.defaultTitle = '';
}
}
我没想到
@HostListener
在我的 getMoviesByGenre()
方法中会失败,但它确实失败了。
它抛出此错误:
TS1146: Declaration expected.
@HostListener('window:scroll', ['$event'])
@HostListener
有可行的替代方法吗?我们需要获取可滚动 div 的
ViewChild
。
@ViewChild('scroller') scroller!: ElementRef<any>;
然后在
ngAfterViewInit
中,我们可以使用rxjsfromEvent
来监听滚动并应用你需要的逻辑
ngAfterViewInit() {
if(scroller?.nativeElement) {
// for window or anything else
// fromEvent(window, 'scroll')
// for some div
fromEvent(scroller.nativeElement, 'scroll').pipe(
startWith(0),
map(x => window?.scrollY),
distinctUntilChanged(),
).subscribe((scrollPos: any) => {
// apply logic here!
});
}
}