You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 11中返回上一页面时如何保持此前滚动到的位置?

Angular 11 路由回退保留滚动位置实现方案

基础结论

该操作不属于浏览器默认行为。SPA单页应用的路由跳转本质是页面局部DOM替换,没有触发完整的页面重载,因此浏览器不会像处理多页应用那样自动保存和恢复滚动位置,需要借助Angular框架能力实现。

实现方案

方案1:使用Angular内置滚动恢复能力(推荐,适配绝大多数场景)

Angular 6及更高版本已经原生支持滚动位置恢复功能,仅需在路由根模块的配置中开启对应参数即可:

// app-routing.module.ts
@NgModule({
  imports: [RouterModule.forRoot(routes, {
    // 开启滚动位置恢复
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

开启后效果:

  • 点击浏览器回退/前进按钮导航时,自动恢复到对应页面之前的滚动位置
  • 点击普通路由链接跳转到新页面时,自动滚动到页面顶部,符合常规使用习惯

如果需要调整顶部偏移(比如页面有固定悬浮头部的场景),可以额外配置scrollOffset参数:

scrollPositionRestoration: 'enabled',
// 滚动时距离顶部预留60px的偏移,适配固定头部场景
scrollOffset: [0, 60]

方案2:手动实现滚动位置存储(适配复杂自定义场景)

如果存在嵌套路由、页面内局部滚动容器、异步内容渲染等特殊场景,内置配置无法满足需求时,可以手动实现滚动位置的存储和恢复:

  1. 首先创建全局服务存储各个路由的滚动位置
// scroll-position.service.ts
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class ScrollPositionService {
  // 存储格式:路由地址 -> [水平滚动位置, 垂直滚动位置]
  private positionStore = new Map<string, [number, number]>();

  save(routeUrl: string, position: [number, number]): void {
    this.positionStore.set(routeUrl, position);
  }

  get(routeUrl: string): [number, number] | undefined {
    return this.positionStore.get(routeUrl);
  }

  clear(routeUrl?: string): void {
    routeUrl ? this.positionStore.delete(routeUrl) : this.positionStore.clear();
  }
}
  1. 在根组件中监听路由事件,完成滚动位置的保存和恢复
// app.component.ts
import { Component } from '@angular/core';
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { ScrollPositionService } from './scroll-position.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(
    private router: Router,
    private scrollService: ScrollPositionService
  ) {
    // 路由开始跳转时,保存当前页面的滚动位置
    this.router.events.pipe(
      filter(event => event instanceof NavigationStart)
    ).subscribe(() => {
      this.scrollService.save(this.router.url, [window.scrollX, window.scrollY]);
    });

    // 路由跳转完成后,恢复对应页面的滚动位置
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      const targetPosition = this.scrollService.get(event.urlAfterRedirects);
      // 等待DOM渲染完成后执行滚动操作
      setTimeout(() => {
        if (targetPosition) {
          window.scrollTo(targetPosition[0], targetPosition[1]);
        } else {
          // 新页面默认滚动到顶部
          window.scrollTo(0, 0);
        }
      }, 0);
    });
  }
}

注意事项

  • 如果滚动容器不是全局window,而是页面内的指定DOM元素,只需要将代码中window的滚动属性替换为对应DOM元素的scrollTop、scrollLeft属性即可
  • 如果页面内容为异步加载(比如列表数据从接口获取后渲染),需要将滚动恢复的逻辑延迟到内容渲染完成后执行,避免出现滚动位置不准确的问题

内容的提问来源于stack exchange,提问作者dangchithao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:06:03