我正在尝试简单地滚动到同一页面上的锚元素。基本上,该人单击"尝试"按钮,然后滚动到页面上ID为"登录"的较低区域。现在,它正在使用基本的id="login"
和<a href="#login"></a>
但它正在跳转到该部分。理想情况下,我希望它滚动到那里。如果我使用的是 Angular4,是否有一些内置的方法可以做到这一点,或者最简单的方法是什么?谢谢!
整个模板...(组件仍为空(
<div id="image-header">
<div id="intro">
<h1 class="text-center">Welcome to ThinkPlan</h1>
<h3 class="text-center">Planning your way</h3>
<a class="btn btn-outline-primary" href="#login" id="view">Try It</a> <!-- Where the user clicks to scroll -->
</div>
</div>
<div class="container" id="info">
<div class="row">
<div class="col-md-12">
<div class="space" id="login"></div> <!-- The place to scroll to -->
<h1 class="text-center">ThinkPlan</h1>
<form class="form-horizontal">
<fieldset>
<legend>Login</legend>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="inputEmail" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="form-group" id="log-btn">
<div class="col-lg-10 col-lg-offset-2">
<button routerLink="/plan" type="submit" class="btn btn-outline-primary">Login</button>
</div>
</div>
<p class="lead text-center">New here? <a routerLink="signup">Sign up.</a></p>
</fieldset>
</form>
</div>
</div>
</div>
对于 Angular 6+,您可以使用:
-
在路由模块中:
imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled'})]
-
然后在您的组件 html 中
<a (click)="onClick('AnchorId')">Click me!</a> <a (click)="onClick('OtherAnchorId')">Click me, too!</a> ... <div id="AnchorId">...</div> ... <div id="OtherAnchorId">...</div>
-
然后在您的组件 ts
中import { ViewportScroller } from '@angular/common'; @Component({ selector: 'component-selector', templateUrl: './mycomponent.component.html' }) export class MyComponent { constructor(private viewportScroller: ViewportScroller) {} public onClick(elementId: string): void { this.viewportScroller.scrollToAnchor(elementId); } }
自动滚动
从 Angular v6 开始,RouterModule
有了新的anchorScrolling
选项。您可以在模块的导入中进行设置:
imports: [
...,
RouterModule.forRoot(routes, {anchorScrolling: 'enabled'})
这样,Angular 将自动滚动到具有给定片段 id 的元素。
⚠️ 但是,当数据异步加载时,这不起作用,请参阅此 Github 问题。 ⚠️
手动滚动
尚无法通过 RouterModule
平滑滚动,但您可以手动完成:
1(获得您的目标,例如ViewChild
:
@ViewChild('pageInfo') pageInfo: ElementRef;
2( 拨打nativeElement
scrollIntoView
:
const targetElement = this.pageInfo.nativeElement
targetElement.scrollIntoView({behavior: "smooth"})
我认为这是更简单的解决方案:
在您的 HTML 中:
<a [routerLink]="['/']" fragment="login"></a>
在您的打字稿中:
ngOnInit() {
this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}
ngAfterViewChecked(): void {
try {
if(this.fragment) {
document.querySelector('#' + this.fragment).scrollIntoView();
}
} catch (e) { }
}
Moerdern单行解决方案:
export class Component implements AfterViewInit {
constructor(
private viewportScroller: ViewportScroller
) { }
ngAfterViewInit(): void {
this.route.fragment.pipe(
first()
).subscribe(fragment => this.viewportScroller.scrollToAnchor(fragment));
}
}
因此,我只是花了大约一个小时的时间使用最新的 Angular 和其他解决方案在初始导航中工作正常,但无论我尝试什么,我都无法让锚点滚动来处理导航历史记录。
换句话说,当我在浏览器中"后退"或"前进"时,URL 会更新,但我无法让 Angular 滚动到正确的位置。 从日志记录来看,Angular 似乎在后退/前进时实际上并没有确认片段,因此没有触发滚动。
我受够了,决定订阅 URL 并在找到片段时手动滚动,这是代码:
ngOnInit() {
this.router.events.subscribe(val => {
if (val instanceof NavigationEnd) {
let fragmentIdx = val.urlAfterRedirects.lastIndexOf('#');
if (fragmentIdx >= 0 && fragmentIdx < val.urlAfterRedirects.length - 1) {
let fragment = val.urlAfterRedirects.substring(fragmentIdx+1);
console.log('fragment: ' + fragment);
document.getElementById(fragment).scrollIntoView();
}
}
})
}
为清楚起见,您必须指定要滚动到的目标元素的id
。
另外,这是我的链接的样子:
<a routerLink="." fragment="anchor-name">Scroll To Anchor</a>
现在,我可以访问不同的锚点,并在历史记录中后退/前进时查看滚动。 希望它对某人有所帮助!
使用 Angular 4 时,使用锚点到同一页面可能会遇到一些问题。
我用这种方式解决了
NG2-页滚动
安装
npm install ng2-page-scroll --save
导入您的应用程序模块.ts
import {Ng2PageScrollModule} from 'ng2-page-scroll';
@NgModule({
imports: [
/* Other imports here */
Ng2PageScrollModule
]
})
export class AppModule {
}
在 HTML 组件中对其进行测试
<a pageScroll href="#test">Testing</a>
<div id="test">
触发ChangeDetection
时都会调用AfterViewCheck()
,因此这是一个糟糕的解决方案。
使用类似AfterViewInit()
public ngAfterViewInit(): void {
this.subscription = this.route.fragment
.subscribe(fragment => {
const targetElement = this.document.querySelector('#' + fragment);
if (fragment && targetElement) {
targetElement.scrollIntoView();
} else {
window.scrollTo(0, 0);
}
});
}
public ngOnDestroy(): void {
this.subscription.unsubscribe();
}
最后,在 Angular 7 中为我工作:
目录:
<h1 id='here'>Here</h1>
元件:
ngAfterViewInit() {
this.route.fragment.subscribe(fragment => {
this.fragment = fragment;
setTimeout(() => this.scrollToAnchor(), 10);
});
}
scrollToAnchor(): void {
try {
if (this.fragment) {
document.querySelector('#' + this.fragment).scrollIntoView();
}
} catch (e) { }
}
goToHere():void{
this.router.navigate(['/product'], { fragment: 'here' });
}
这是一个更详细的例子,可以添加到Sarah Dubois上面的答案中。
导入路由器模块。
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
constructor(private route:ActivatedRoute,
private router:Router) {
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event.url) {
this.route.fragment.subscribe(fragment => this.fragment = fragment);
}
}
});
}
ngAfterViewChecked(): void {
try {
if(this.fragment != null) {
document.querySelector("a[name="+this.fragment+"]").scrollIntoView();
}
} catch (e) {
//console.log(e, 'error');
}
}
我喜欢querySelector的使用,它将为您提供很多选项,以转到要滚动到的元素。 https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
这适用于 Angular 8 :)