Angular:scrollIntoView 在 ngAfterViewInit 中没有 setTimeout 时无法处理路线更改

问题描述 投票:0回答:1

我有一个 Angular 组件,我想在路线更改时使用scrollIntoView。这是我的组件中的相关代码片段:

@ViewChild('structure') structure: ElementRef | undefined;
legacyRoute: string = '';

constructor(private apiService: ApiService, private router: ActivatedRoute, private route: Router, private cdRef: ChangeDetectorRef) { }


ngAfterViewInit() {
  this.router.paramMap.subscribe(params => {
    this.legacyRoute = params.get('id') || '';
    console.log("checking legacy after param map subscription", this.legacyRoute);
    setTimeout(() => { 
      if (this.legacyRoute && this.structure && this.structure.nativeElement) {
        console.log("Running scrollIntoView", this.legacyRoute, this.structure, this.structure.nativeElement);
        this.structure.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'start' });
      }
    }, 1000)    
  });
}

问题: scrollIntoView 函数在页面刷新时可以正常工作,但在 Angular 路由更改时则无法正常工作。我添加了一个 setTimeout 来延迟该函数,这使得它可以工作,但我知道这不是一个可靠的解决方案。

我尝试过的:

  • 删除 setTimeout 会导致scrollIntoView在路线更改时无法正常工作。

  • 调用scrollIntoView之前确保this.struct.nativeElement有效。

  • 使用 ngAfterViewChecked() 代替 ngAfterViewInit()

预期行为: 我希望在 Angular 应用程序中导航到不同的路线时,scrollIntoView 能够正确执行,而不依赖于 setTimeout。

其他背景:

  • 角度版本:
  "dependencies": {
    "@angular/animations": "^17.3.0",
    "@angular/cdk": "^17.3.9",
    "@angular/common": "^17.3.0",
    "@angular/compiler": "^17.3.0",
    "@angular/core": "^17.3.0",
    "@angular/forms": "^17.3.0",
    "@angular/platform-browser": "^17.3.0",
    "@angular/platform-browser-dynamic": "^17.3.0",
    "@angular/platform-server": "^17.3.0",
    "@angular/router": "^17.3.0",
    "@angular/ssr": "^17.3.7",
    "@ngrx/store": "^17.2.0",
    "express": "^4.18.2",
    "force": "^0.0.3",
    "primeicons": "^7.0.0",
    "primeng": "^17.17.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.3"
  }
  • struct 是一个 ViewChild 或 ElementRef ,指向应该应用scrollIntoView的 DOM 元素。 <-- something like
    -->
 

我的标题

由于我是 Angular 的新手,我想确保我没有忽略任何重要的事情。您的帮助对我来说意义重大,我真诚地感谢您的时间和帮助。预先感谢您!

javascript angular typescript settimeout angular-router
1个回答
0
投票

也许您可以尝试监听路由器导航结束事件,以确保导航已完成以及信号效果。

这也适用于初始呼叫。我会尝试这样的事情。

private readonly navigationEnd = toSignal(
  this.router.events.pipe(filter((event): event is NavigationEnd => event instanceof NavigationEnd))
)

private readonly structure = viewChild('structur')

constructor() {
  effect(() => {
    // maybe called 2 times if navigation has been ended
    // and if structure has been resolved
    const navigationEnd = this.navitationEnd();
    const structure = this.structure();

    // scroll into view
  })
}
© www.soinside.com 2019 - 2024. All rights reserved.