首页 > 解决方案 > 路由器 anchorScrolling 不适用于 Material 的 mat-sidenav-container [全屏]

问题描述

锚滚动基于RouterModule视口可滚动区域,mat-sidenav-container当与属性一起使用时将 ifself 设置为 100% 高度fullscreen,没有视口溢出RouterModule可更改。

<mat-sidenav-container fullscreen>
    <mat-sidenav-content></mat-sidenav-content>
</mat-sidenav-content>

在上面的示例中,所有可滚动内容都存在于mat-sidenav-content.

有没有办法代替视口作为滚动容器参考RouterModulemat-sidenav-container

请参阅StackBlitz 示例。查看没有全屏的工作版本

标签: angularangular-materialangular-material2angular-routinganchor-scroll

解决方案


我现在正在遇到一模一样的问题。我通过以下方式解决了它:

  1. 对于mat-side-nav-container,我没有设置'height',而是设置'min-height'为100%,这样可滚动的元素就是body,而不是sidenav容器,但万一内容少与视口相比,容器仍会拉伸以覆盖它。请记住,这可能会影响您的布局,具体取决于您的实现,但这对于此解决方案的工作是绝对必要的。
  2. mat-toolbar 的高度(在 mat-sidenav-container 上方)是 64px,我为正在滚动的元素保留的边距是 16px,因此 (64 + 16) 是 y 偏移量
  3. 在 app.module.ts 中,NgModule 的内部导入
RouterModule.forRoot(
      routes,
      {
        anchorScrolling: 'enabled',
        scrollOffset: [0, 64 + 16]
      }),
  1. 假设 mat-sidenav-container 位于 app.component.html 中,我在 ngOnInit() 中的 app.component.ts 中添加了以下内容。(请记住要预防由于订阅引起的内存泄漏,虽然这是应用程序组件,所以这并不重要)
this.router.events
        .pipe(

          //take only scroll events that have an anchor specified
          filter(e => e instanceof Scroll && !!e.anchor),

          //wait for the DOM to resolve. It worked with 10, but it was a small test case
          //so I used 100 just in case
          delay(100),

          //take the element that the anchor points to
          map((e: Scroll) => document.getElementById(e.anchor)),

          //ignore if no element was found
          filter(el => !!el)
        )
        .subscribe(el => 
            document.scrollingElement
                 .scroll(
                     0, 
                     window.scrollY + el.getBoundingClientRect().top - (64 + 16)
                 )));

其他改进:

  • 无需对 y 偏移进行硬编码 - 可以查询 mat-toobar 的 clientHeight 和滚动到的元素的 clientTop,然后添加它们以获得偏移
  • 我只测试了它是否可以滚动到 mat-sidenav-content 的直接后代元素。也许这个逻辑可以扩展为适用于嵌套元素、嵌套路由等等等

推荐阅读