Menggunakannya Routersendiri akan menyebabkan masalah yang tidak dapat Anda atasi sepenuhnya untuk mempertahankan pengalaman browser yang konsisten. Menurut pendapat saya metode terbaik adalah dengan hanya menggunakan kebiasaan directivedan biarkan ini mereset gulir saat klik. Hal yang baik tentang ini, adalah bahwa jika Anda berada di sama urldengan yang Anda klik, halaman akan menggulir kembali ke atas juga. Ini konsisten dengan situs web normal. Dasardirective bisa terlihat seperti ini:
import {Directive, HostListener} from '@angular/core';
@Directive({
selector: '[linkToTop]'
})
export class LinkToTopDirective {
@HostListener('click')
onClick(): void {
window.scrollTo(0, 0);
}
}
Dengan penggunaan berikut:
<a routerLink="/" linkToTop></a>
Ini akan cukup untuk sebagian besar kasus penggunaan, tapi saya bisa membayangkan beberapa masalah yang mungkin timbul dari ini:
- Tidak berfungsi
universal karena penggunaanwindow
- Kecepatan kecil berdampak pada deteksi perubahan, karena dipicu oleh setiap klik
- Tidak ada cara untuk menonaktifkan arahan ini
Sebenarnya cukup mudah untuk mengatasi masalah ini:
@Directive({
selector: '[linkToTop]'
})
export class LinkToTopDirective implements OnInit, OnDestroy {
@Input()
set linkToTop(active: string | boolean) {
this.active = typeof active === 'string' ? active.length === 0 : active;
}
private active: boolean = true;
private onClick: EventListener = (event: MouseEvent) => {
if (this.active) {
window.scrollTo(0, 0);
}
};
constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
private readonly elementRef: ElementRef,
private readonly ngZone: NgZone
) {}
ngOnDestroy(): void {
if (isPlatformBrowser(this.platformId)) {
this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
}
}
ngOnInit(): void {
if (isPlatformBrowser(this.platformId)) {
this.ngZone.runOutsideAngular(() =>
this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
);
}
}
}
Ini memperhitungkan sebagian besar kasus penggunaan, dengan penggunaan yang sama seperti kasus dasar, dengan keuntungan mengaktifkan / menonaktifkannya:
<a routerLink="/" linkToTop></a> <!-- always active -->
<a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->
iklan, jangan baca jika Anda tidak ingin diiklankan
Perbaikan lain dapat dilakukan untuk memeriksa apakah browser mendukung passiveacara atau tidak . Ini akan memperumit kode sedikit lebih, dan agak tidak jelas jika Anda ingin menerapkan semua ini dalam arahan / templat kustom Anda. Itu sebabnya saya menulis perpustakaan kecil yang dapat Anda gunakan untuk mengatasi masalah ini. Untuk memiliki fungsi yang sama seperti di atas, dan dengan passiveacara yang ditambahkan , Anda dapat mengubah arahan Anda untuk ini, jika Anda menggunakan ng-event-optionsperpustakaan. Logikanya ada di dalam click.pnbpendengar:
@Directive({
selector: '[linkToTop]'
})
export class LinkToTopDirective {
@Input()
set linkToTop(active: string|boolean) {
this.active = typeof active === 'string' ? active.length === 0 : active;
}
private active: boolean = true;
@HostListener('click.pnb')
onClick(): void {
if (this.active) {
window.scrollTo(0, 0);
}
}
}
RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })