【问题标题】:Router anchorScrolling does not work with Material's mat-sidenav-container[fullscreen]路由器 anchorScrolling 不适用于 Material 的 mat-sidenav-container [全屏]
【发布时间】:2019-03-14 11:45:17
【问题描述】:

RouterModule 锚滚动基于视口可滚动区域,当mat-sidenav-containerfullscreen 属性一起使用时将 ifself 设置为 100% 高度,RouterModule 不会发生视口溢出来更改。

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

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

有没有办法让RouterModule 使用mat-sidenav-container 而不是视口作为滚动容器引用?

请参阅StackBlitz Example。 请参阅working version without fullscreen

【问题讨论】:

    标签: angular angular-material angular-material2 angular-routing anchor-scroll


    【解决方案1】:

    我遇到了完全相同的问题。 我通过以下方式解决了它:

    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)
                     )));
    

    其他改进:

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

    【讨论】:

    • 不是解决方案,但适合的解决方法。谢谢。另外,我建议任何人使用路由器的ExtraOptions 键的scrollOffset 选项。
    • 我知道,我也在努力解决这个问题。 :( 使用 Angular 进行锚点滚动非常糟糕。尤其是对于延迟加载的模块。如果你添加路由器动画......好吧......我们甚至不要到达那里。另外,因为这个解决方案滚动两次,如果它会损害用户体验你将从 A 页面上的锚点转到 B 页面上的锚点。所以我使用了 1000 的延迟,这样至少感觉更好。我相信他们会做一段时间,什么时候?我不知道跨度>
    【解决方案2】:

    是否有 mat-sidenav-content 解决方案? 作为一种解决方法,我正在订阅路由器事件并查看 Scroll.anchor, 然后按照 Using anchor link #id in Angular 6 我可以影响视图子的平滑滚动...

    例如

    在 html 中:

      <a routerLink="/menu" fragment="pizza">Pizza</a>
      ...
      <div #pizza>...</div>
    

    在组件中:

        @ViewChild( 'pizza' ) pizza: ElementRef
    
        this.router.events.subscribe( (e:RouterEvent) => {
            if ( e instanceof Scroll ) {
              if ( e.anchor ==== 'pizza' ) {
                this.pizza.nativeElement.scrollIntoView( ... );
              }
            }
        } );
    

    【讨论】:

    • 不是一个解决方案,但它是合适的解决方法。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 2018-11-21
    • 1970-01-01
    相关资源
    最近更新 更多