Javascript 角2中的自动滚动
我在Angular 2中遇到一个问题,从一条路线更改到另一条路线不会自动滚动到新视图的顶部。我意识到Angular 1允许将Javascript 角2中的自动滚动,javascript,angular,angular2-routing,Javascript,Angular,Angular2 Routing,我在Angular 2中遇到一个问题,从一条路线更改到另一条路线不会自动滚动到新视图的顶部。我意识到Angular 1允许将autoscroll属性添加到HTML元素,而其他人则提出了一些简单的javascript(例如window.scroll(0,0))来强制视图在加载时滚动到顶部 然而,我不知道如何用Angular 2实现这一点。有人知道如何做到这一点吗?更新 目前没有自动方式 另见 另见 更新 在新的路由器V3 beta.2中,您可以传递带有路由器链接和路由器导航的片段 <a [r
autoscroll
属性添加到HTML元素,而其他人则提出了一些简单的javascript(例如window.scroll(0,0)
)来强制视图在加载时滚动到顶部
然而,我不知道如何用Angular 2实现这一点。有人知道如何做到这一点吗?更新 目前没有自动方式 另见 另见
更新 在新的路由器V3 beta.2中,您可以传递带有路由器链接和路由器导航的片段
<a [routerLink]="..." fragment="top">
测试版
router.events
.filter(e => e instanceof NavigationEnd)
.subscribe(() => {
window.scrollTo(0, 0);
});
我也有同样的问题。根据冈特的回答,我发现Angular的2 RC.1新路由器并没有直接暴露出可观测的物体。相反,它有一个用于此目的的
changes
属性。RC.1的解决方法是:
this._router.changes.subscribe(() => {
window.scrollTo(0, 0);
});
较新的RCs(>=RC.3)似乎没有公开可观察到的更改,它可能已经被重命名为或
他们完全“神奇”的文档似乎没有提供任何关于正在做什么的信息,所以我猜你是在玩俄罗斯轮盘赌。或者扔硬币什么的
从回答中,似乎事件
可观察返回有关导航状态的事件:
对于那些发现window.scrollTo(0,0)
不起作用的人(我猜测是因为材质设计方面的原因,但完全是猜测),请使用以下方法:
我在每页的ngOnInit中使用if(this.router.navigated)来确定是否使用window.scrollTo(0,0)。这将涵盖大多数路由到页面的情况,同时保留滚动位置(如果单击浏览器后退按钮)
if(this.router.navigated) {
window.scrollTo(0, 0);
}
您可以在这里看到:,从Angular 2.0.0开始,您必须使用“router.events.subscribe”
因此,自动将scrool放在所有页面顶部的一个好解决方案是使用如下AppComponent:
import {Component} from '@angular/core';
import {Router, NavigationEnd} from "@angular/router";
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private router: Router) {
router.events.subscribe((val) => {
if (val instanceof NavigationEnd){
window.scrollTo(0,0);
}
});
}
}
由我测试的100%溶液:
constructor(router:Router){
this.router.events.subscribe(() => {
window.scrollTo(0, 0);
});
}
我正在使用material sidenav,但我无法得到任何建议的答案。以下是我的工作解决方案:
import { Router, NavigationEnd } from '@angular/router';
...
constructor(
private router: Router,
) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
document.querySelector('.mat-sidenav-content').scrollTop = 0;
}
}
}
我没有在每个组件中编写代码,而是在一个地方添加了以下代码-
<router-outlet (activate)="onActivate($event)"></router-outlet>
onActivate(e) {
window.scrollTo(0, 0);
}
激活(e){
滚动到(0,0);
}
我在中发布了这篇文章,但我会在这里再次发布
我的团队一直在angular.io上使用。只要做一个服务,像往常一样注入它。然后,在ngAfterViewInit的每个页面上,只要调用[scroll service variable name].scrollToTop()即可。最后,您需要将其添加到index.html中的
顶部:
服务代码:
import { Injectable, Inject } from '@angular/core';
import { PlatformLocation } from '@angular/common';
import { DOCUMENT } from '@angular/platform-browser';
import {fromEvent} from 'rxjs/observable/fromEvent';
export const topMargin = 16;
/**
* A service that scrolls document elements into view
*/
@Injectable()
export class ScrollService {
private _topOffset: number | null;
private _topOfPageElement: Element;
// Offset from the top of the document to bottom of any static elements
// at the top (e.g. toolbar) + some margin
get topOffset() {
if (!this._topOffset) {
const toolbar = this.document.querySelector('md-toolbar.app-toolbar');
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
}
return this._topOffset;
}
get topOfPageElement() {
if (!this._topOfPageElement) {
this._topOfPageElement = this.document.getElementById('top-of-page') || this.document.body;
}
return this._topOfPageElement;
}
constructor(
@Inject(DOCUMENT) private document: any,
private location: PlatformLocation) {
// On resize, the toolbar might change height, so "invalidate" the top offset.
fromEvent(window, 'resize').subscribe(() => this._topOffset = null);
}
/**
* Scroll to the element with id extracted from the current location hash fragment.
* Scroll to top if no hash.
* Don't scroll if hash not found.
*/
scroll() {
const hash = this.getCurrentHash();
const element: HTMLElement = hash
? this.document.getElementById(hash)
: this.topOfPageElement;
this.scrollToElement(element);
}
/**
* Scroll to the element.
* Don't scroll if no element.
*/
scrollToElement(element: Element) {
if (element) {
element.scrollIntoView();
if (window && window.scrollBy) {
// Scroll as much as necessary to align the top of `element` at `topOffset`.
// (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the
// way to the top, because the viewport is larger than the height of the content after the
// element.)
window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset);
// If we are very close to the top (<20px), then scroll all the way up.
// (This can happen if `element` is at the top of the page, but has a small top-margin.)
if (window.pageYOffset < 20) {
window.scrollBy(0, -window.pageYOffset);
}
}
}
}
/** Scroll to the top of the document. */
scrollToTop() {
this.scrollToElement(this.topOfPageElement);
}
/**
* Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
*/
private getCurrentHash() {
return this.location.hash.replace(/^#/, '');
}
}
从'@angular/core'导入{Injectable,injection};
从“@angular/common”导入{PlatformLocation};
从“@angular/platform browser”导入{DOCUMENT};
从'rxjs/observable/fromEvent'导入{fromEvent};
导出常数topMargin=16;
/**
*将文档元素滚动到视图中的服务
*/
@可注射()
导出类滚动服务{
private _topOffset:number | null;
private _topOfPageElement:Element;
//从文档顶部到任何静态元素底部的偏移量
//在顶部(例如工具栏)+一些边距
获取topOffset(){
如果(!this.\u topOffset){
const-toolbar=this.document.querySelector('md-toolbar.app-toolbar');
这._topOffset=(toolbar和toolbar.clientHeight | | 0)+topMargin;
}
返回此项。\u topOffset;
}
获取topOfPageElement(){
如果(!this.\u topOfPageElement){
this._topOfPageElement=this.document.getElementById('top-of-page')| | this.document.body;
}
返回此.\u topOfPageElement;
}
建造师(
@注入(文件)私人文件:任何,
专用位置:平台位置){
//调整大小时,工具栏可能会更改高度,因此“使顶部偏移无效”。
fromEvent(窗口,“调整大小”).subscribe(()=>this.\u topOffset=null);
}
/**
*滚动到id从当前位置哈希片段提取的元素。
*如果没有哈希,则滚动到顶部。
*如果未找到哈希,则不滚动。
*/
卷轴(){
const hash=this.getCurrentHash();
常量元素:HTMLElement=hash
?this.document.getElementById(散列)
:this.topOfPageElement;
此.scrollToElement(元素);
}
/**
*滚动到元素。
*如果没有元素,则不要滚动。
*/
scrollToElement(元素:元素){
if(元素){
元素。scrollIntoView();
if(window&&window.scrollBy){
//尽可能多地滚动以对齐“topOffset”处的“element”顶部。
//(通常,`.top`将为0,除非该元素不能在所有时间滚动。)
//由于视口的高度大于
//元素。)
scrollBy(0,element.getBoundingClientRect().top-this.topOffset);
//如果我们非常接近顶部(我更喜欢这个答案,因为代码实际上是编译的(其他答案缺少paren)我还将路由器作为私有成员注入,这应该是常见的做法。同意。我建议使用NavigationEnd作为scrolling@GünterZöchbauer我怎么能在RC5中做到这一点?请告诉我know@GünterZöchbauer,我认为代码可能有几个错误:NativationEnd应该是“NavigationEnd”,应该是“e=>e instanceof NavigationEnd”。猜对了!window.scrollTo()不起作用的原因是因为您不想滚动窗口。如果您使用的是,您想滚动窗口中的内容元素。请参阅Tyson的答案。确实,很优雅!
import { Router, NavigationEnd } from '@angular/router';
...
constructor(
private router: Router,
) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
document.querySelector('.mat-sidenav-content').scrollTop = 0;
}
}
}
<router-outlet (activate)="onActivate($event)"></router-outlet>
onActivate(e) {
window.scrollTo(0, 0);
}
import { Injectable, Inject } from '@angular/core';
import { PlatformLocation } from '@angular/common';
import { DOCUMENT } from '@angular/platform-browser';
import {fromEvent} from 'rxjs/observable/fromEvent';
export const topMargin = 16;
/**
* A service that scrolls document elements into view
*/
@Injectable()
export class ScrollService {
private _topOffset: number | null;
private _topOfPageElement: Element;
// Offset from the top of the document to bottom of any static elements
// at the top (e.g. toolbar) + some margin
get topOffset() {
if (!this._topOffset) {
const toolbar = this.document.querySelector('md-toolbar.app-toolbar');
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
}
return this._topOffset;
}
get topOfPageElement() {
if (!this._topOfPageElement) {
this._topOfPageElement = this.document.getElementById('top-of-page') || this.document.body;
}
return this._topOfPageElement;
}
constructor(
@Inject(DOCUMENT) private document: any,
private location: PlatformLocation) {
// On resize, the toolbar might change height, so "invalidate" the top offset.
fromEvent(window, 'resize').subscribe(() => this._topOffset = null);
}
/**
* Scroll to the element with id extracted from the current location hash fragment.
* Scroll to top if no hash.
* Don't scroll if hash not found.
*/
scroll() {
const hash = this.getCurrentHash();
const element: HTMLElement = hash
? this.document.getElementById(hash)
: this.topOfPageElement;
this.scrollToElement(element);
}
/**
* Scroll to the element.
* Don't scroll if no element.
*/
scrollToElement(element: Element) {
if (element) {
element.scrollIntoView();
if (window && window.scrollBy) {
// Scroll as much as necessary to align the top of `element` at `topOffset`.
// (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the
// way to the top, because the viewport is larger than the height of the content after the
// element.)
window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset);
// If we are very close to the top (<20px), then scroll all the way up.
// (This can happen if `element` is at the top of the page, but has a small top-margin.)
if (window.pageYOffset < 20) {
window.scrollBy(0, -window.pageYOffset);
}
}
}
}
/** Scroll to the top of the document. */
scrollToTop() {
this.scrollToElement(this.topOfPageElement);
}
/**
* Return the hash fragment from the `PlatformLocation`, minus the leading `#`.
*/
private getCurrentHash() {
return this.location.hash.replace(/^#/, '');
}
}