这是另一个参考 JavierFuentes 答案的解决方法:
<a [routerLink]="['self-route', id]" fragment="some-element" (click)="gotoHashtag('some-element')">Jump to Element</a>
在脚本中:
import {ActivatedRoute} from "@angular/router";
import {Subscription} from "rxjs/Subscription";
export class Links {
private scrollExecuted: boolean = false;
constructor(private route: ActivatedRoute) {}
ngAfterViewChecked() {
if (!this.scrollExecuted) {
let routeFragmentSubscription: Subscription;
routeFragmentSubscription = this.route.fragment.subscribe(fragment => {
if (fragment) {
let element = document.getElementById(fragment);
if (element) {
element.scrollIntoView();
this.scrollExecuted = true;
// Free resources
setTimeout(
() => {
console.log('routeFragmentSubscription unsubscribe');
routeFragmentSubscription.unsubscribe();
}, 0);
}
}
});
}
}
gotoHashtag(fragment: string) {
const element = document.querySelector("#" + fragment);
if (element) element.scrollIntoView(element);
}
}
这允许用户直接滚动到元素,如果用户直接登陆在 url 中有标签的页面。
但在这种情况下,我在ngAfterViewChecked 中订阅了路由片段,但ngAfterViewChecked() 每次ngDoCheck 都会被连续调用,并且它不允许用户滚动回顶部,所以routeFragmentSubscription.unsubscribe 在之后调用视图滚动到元素后超时 0 毫秒。
另外gotoHashtag 方法被定义为当用户专门点击锚标签时滚动到元素。
更新:
如果 url 有查询字符串,则锚点中的[routerLink]="['self-route', id]" 不会保留查询字符串。我尝试了以下解决方法:
<a (click)="gotoHashtag('some-element')">Jump to Element</a>
constructor( private route: ActivatedRoute,
private _router:Router) {
}
...
...
gotoHashtag(fragment: string) {
let url = '';
let urlWithSegments = this._router.url.split('#');
if(urlWithSegments.length){
url = urlWithSegments[0];
}
window.location.hash = fragment;
const element = document.querySelector("#" + fragment);
if (element) element.scrollIntoView(element);
}