Javascript Angular 5 在每次点击路线时滚动到顶部

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48048299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:00:35  来源:igfitidea点击:

Angular 5 Scroll to top on every Route click

javascriptangulartypescriptscrolltopangular-router

提问by raihan

I am using angular 5. I have a dashboard where I have few sections with small content and few sections with so large content that I am facing a problem when changing router while going to top. Every time I need to scroll to go to top. Can anyone help me to solve this issue so that when I change the router my view always stay at the top.

我正在使用 angular 5。我有一个仪表板,其中很少有内容很小的部分,而很少有内容很大的部分,以至于在进入顶部时更改路由器时遇到问题。每次我需要滚动到顶部。谁能帮我解决这个问题,这样当我更换路由器时,我的视图始终保持在顶部。

Thanks in advance.

提前致谢。

回答by Vega

There some solutions, make sure to check them all :)

有一些解决方案,请确保全部检查:)

The router outlet will emit the activateevent any time a new component is being instantiated, so we could use (activate)to scroll (for example) to the top:

路由器插座将activate在实例化新组件时发出事件,因此我们可以使用(activate)滚动(例如)到顶部:

app.component.html

应用程序组件.html

<router-outlet (activate)="onActivate($event)" ></router-outlet>

app.component.ts

app.component.ts

onActivate(event) {
    window.scroll(0,0);
    //or document.body.scrollTop = 0;
    //or document.querySelector('body').scrollTo(0,0)
    ...
}

or using this answerto smooth scroll

或使用此答案平滑滚动

    onActivate(event) {
        let scrollToTop = window.setInterval(() => {
            let pos = window.pageYOffset;
            if (pos > 0) {
                window.scrollTo(0, pos - 20); // how far to scroll on each step
            } else {
                window.clearInterval(scrollToTop);
            }
        }, 16);
    }


If you wish to be selective, say not every component should trigger the scrolling, you can check it:

如果你想有选择性,说不是每个组件都应该触发滚动,你可以检查它:

onActivate(e) {
    if (e.constructor.name)==="login"{ // for example
            window.scroll(0,0);
    }
}



从 Angular6.1 开始,我们也可以 { scrollPositionRestoration: 'enabled' }{ scrollPositionRestoration: 'enabled' }在急切加载的模块上使用,它将应用于所有路由:

RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

It will also do the smooth scrolling. However this has the inconvenient for doing it on every routing.

它还将进行平滑滚动。然而,这对于在每个路由上都执行它有不便之处。



另一种解决方案是在路由器动画上进行顶部滚动。在要滚动到顶部的每个过渡中添加以下内容:

query(':enter, :leave', style({ position: 'fixed' }), { optional: true }),

回答by Nimezzz

If you face this problem in Angular 6, you can fix it by adding the parameter scrollPositionRestoration: 'enabled'to app-routing.module.ts 's RouterModule:

如果你在 Angular 6 中遇到这个问题,你可以通过将参数添加scrollPositionRestoration: 'enabled'到 app-routing.module.ts 的 RouterModule来解决它:

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})

回答by GeoRover

EDIT:For Angular 6+, please use Nimesh Nishara Indimagedara's answer mentioning:

编辑:对于 Angular 6+,请使用 Nimesh Nishara Indimagedara 的回答提到:

RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
});


Original Answer:

原答案:

If all fails, then create some empty HTML element (eg: div) at the top (or desired scroll to location) with id="top" on template (or parent template):

如果一切都失败了,那么在模板(或父模板)上使用 id="top" 在顶部(或所需的滚动到位置)创建一些空的 HTML 元素(例如:div):

<div id="top"></div>

And in component:

在组件中:

  ngAfterViewInit() {
    // Hack: Scrolls to top of Page after page view initialized
    let top = document.getElementById('top');
    if (top !== null) {
      top.scrollIntoView();
      top = null;
    }
  }

回答by Abdul Rafay

Now there's a built in solution available in Angular 6.1 with scrollPositionRestorationoption.

现在,Angular 6.1 提供了一个内置解决方案,并带有scrollPositionRestoration选项。

See my answeron Angular 2 Scroll to top on Route Change.

请参阅Angular 2 的回答Scroll to top on Route Change

回答by Sal_Vader_808

Although @Vega provides the direct answer to your question, there are issues. It breaks the browser's back/forward button. If you're user clicks the browser back or forward button, they lose their place and gets scrolled way at the top. This can be a bit of a pain for your users if they had to scroll way down to get to a link and decided to click back only to find the scrollbar had been reset to the top.

尽管@Vega 为您的问题提供了直接答案,但还是存在问题。它打破了浏览器的后退/前进按钮。如果您是用户单击浏览器的后退或前进按钮,他们会失去位置并在顶部滚动。如果您的用户不得不向下滚动才能找到链接,并决定单击返回后才发现滚动条已重置到顶部,那么这对您的用户来说可能会有点痛苦。

Here's my solution to the problem.

这是我对问题的解决方案。

export class AppComponent implements OnInit {
  isPopState = false;

  constructor(private router: Router, private locStrat: LocationStrategy) { }

  ngOnInit(): void {
    this.locStrat.onPopState(() => {
      this.isPopState = true;
    });

    this.router.events.subscribe(event => {
      // Scroll to top if accessing a page, not via browser history stack
      if (event instanceof NavigationEnd && !this.isPopState) {
        window.scrollTo(0, 0);
        this.isPopState = false;
      }

      // Ensures that isPopState is reset
      if (event instanceof NavigationEnd) {
        this.isPopState = false;
      }
    });
  }
}

回答by Zohab Ali

In my case I just added

就我而言,我刚刚添加了

window.scroll(0,0);

in ngOnInit()and its working fine.

ngOnInit()和它的工作正常。

回答by ivin antony

if your using mat-sidenav give an id to the router outlet( if you have a parent and child router outlets) and use activate function in it <router-outlet id="main-content" (activate)="onActivate($event)">and use this 'mat-sidenav-content' query selector to scroll top onActivate(event) { document.querySelector("mat-sidenav-content").scrollTo(0, 0); }

如果您使用 mat-sidenav 为路由器插座提供 id(如果您有父路由器插座和子路由器插座)并在其中使用激活功能 <router-outlet id="main-content" (activate)="onActivate($event)">并使用此“mat-sidenav-content”查询选择器滚动顶部 onActivate(event) { document.querySelector("mat-sidenav-content").scrollTo(0, 0); }

回答by Vikas

From Angular Version 6+ No need to use window.scroll(0,0)

从 Angular 版本 6+ 开始不需要使用 window.scroll(0,0)

For Angular version 6+from @docs
Represents options to configure the router.

对于6+来自@ Represents 的Angular 版本,用于配置路由器的选项。docs

interface ExtraOptions {
  enableTracing?: boolean
  useHash?: boolean
  initialNavigation?: InitialNavigation
  errorHandler?: ErrorHandler
  preloadingStrategy?: any
  onSameUrlNavigation?: 'reload' | 'ignore'
  scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'
  anchorScrolling?: 'disabled' | 'enabled'
  scrollOffset?: [number, number] | (() => [number, number])
  paramsInheritanceStrategy?: 'emptyOnly' | 'always'
  malformedUriErrorHandler?: (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree
  urlUpdateStrategy?: 'deferred' | 'eager'
  relativeLinkResolution?: 'legacy' | 'corrected'
}

One can use scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'in

人们可以使用scrollPositionRestoration?: 'disabled' | 'enabled' | 'top'

Example:

例子:

RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'|'top' 
});

And if one requires to manually control the scrolling, No need to use window.scroll(0,0)Instead from Angular V6 common package has introduced ViewPortScoller.

如果需要手动控制滚动,无需使用window.scroll(0,0)Angular V6 通用包中引入的替代ViewPortScoller

abstract class ViewportScroller {
  static ngInjectableDef: defineInjectable({ providedIn: 'root', factory: () => new BrowserViewportScroller(inject(DOCUMENT), window) })
  abstract setOffset(offset: [number, number] | (() => [number, number])): void
  abstract getScrollPosition(): [number, number]
  abstract scrollToPosition(position: [number, number]): void
  abstract scrollToAnchor(anchor: string): void
  abstract setHistoryScrollRestoration(scrollRestoration: 'auto' | 'manual'): void
}

Usage is pretty Straightforward Example:

用法非常简单 示例:

import { Router } from '@angular/router';
import {  ViewportScroller } from '@angular/common'; //import
export class RouteService {

  private applicationInitialRoutes: Routes;
  constructor(
    private router: Router;
    private viewPortScroller: ViewportScroller//inject
  )
  {
   this.router.events.pipe(
            filter(event => event instanceof NavigationEnd))
            .subscribe(() => this.viewPortScroller.scrollToPosition([0, 0]));
}

回答by Vijay Barot

You just need to create a function which contains adjustment of scrolling of your screen

您只需要创建一个包含调整屏幕滚动的功能

for example

例如

window.scroll(0,0) OR window.scrollTo() by passing appropriate parameter.

window.scrollTo(xpos, ypos) --> expected parameter.

window.scrollTo(xpos, ypos) --> 预期参数。

回答by Jared Whipple

I keep looking for a built in solution to this problem like there is in AngularJS. But until then this solution works for me, It's simple, and preserves back button functionality.

我一直在寻找解决这个问题的内置解决方案,就像在 AngularJS 中一样。但在那之前,这个解决方案对我有用,它很简单,并且保留了后退按钮的功能。

app.component.html

应用程序组件.html

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

app.component.ts

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

Answer from zurfyxoriginal post

来自zurfyx原帖的回答