Menggunakannya Router
sendiri 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 directive
dan biarkan ini mereset gulir saat klik. Hal yang baik tentang ini, adalah bahwa jika Anda berada di sama url
dengan 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 passive
acara 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 passive
acara yang ditambahkan , Anda dapat mengubah arahan Anda untuk ini, jika Anda menggunakan ng-event-options
perpustakaan. Logikanya ada di dalam click.pnb
pendengar:
@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' })