我希望在我的Angular2页面上添加一些链接,当点击时,可以跳转到该页面内的特定位置,就像常规的标签一样。因此,这些链接可能类似于:
/users/123#userInfo
/users/123#userPhoto
/users/123#userLikes
我认为我不需要HashLocationStrategy,因为我对Angular2的常规方式感到满意,但是如果我直接添加<base href="/">
,链接实际上会跳转到根目录,而不是同一页的其他位置。非常感谢您提供任何指导。
更新
现在已经支持该功能
<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});
将以下代码添加到您的组件中以实现滚动
import {ActivatedRoute} from '@angular/router'; // <-- do not forget to import
private fragment: string;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}
ngAfterViewInit(): void {
try {
document.querySelector('#' + this.fragment).scrollIntoView();
} catch (e) { }
}
翻译
这是一个已知问题,可以在https://github.com/angular/angular/issues/6595上进行跟踪。
很抱歉回答有点晚了。在Angular路由文档中有一个预定义的函数可以帮助我们使用哈希标记进行页面锚定,即 anchorScrolling:'enabled'
步骤1:首先在app.module.ts文件中导入RouterModule:
imports:[
BrowserModule,
FormsModule,
RouterModule.forRoot(routes,{
anchorScrolling: 'enabled'
})
],
步骤二:前往HTML页面,创建导航并添加两个重要属性,如[routerLink]和fragment,以匹配相应的Div ID:
<ul>
<li> <a [routerLink] = "['/']" fragment="home"> Home </a></li>
<li> <a [routerLink] = "['/']" fragment="about"> About Us </a></li>
<li> <a [routerLink] = "['/']" fragment="contact"> Contact Us </a></li>
</ul>
步骤-3:- 通过将ID名称与片段匹配来创建一个部分/ div:
<section id="home" class="home-section">
<h2> HOME SECTION </h2>
</section>
<section id="about" class="about-section">
<h2> ABOUT US SECTION </h2>
</section>
<section id="contact" class="contact-section">
<h2> CONTACT US SECTION </h2>
</section>
供参考,我通过创建一个小演示来帮助解决您的问题,以下是示例:
scrollPositionRestoration: 'enabled'
即可 :) - Mickaël<a [routerLink]="['somepath']" fragment="Test">Jump to 'Test' anchor </a>
this._router.navigate( ['/somepath', id ], {fragment: 'test'});
在需要“跳转到”行为的组件(父组件)中,添加以下代码:
import { Router, NavigationEnd } from '@angular/router';
class MyAppComponent {
constructor(router: Router) {
router.events.subscribe(s => {
if (s instanceof NavigationEnd) {
const tree = router.parseUrl(router.url);
if (tree.fragment) {
const element = document.querySelector("#" + tree.fragment);
if (element) { element.scrollIntoView(true); }
}
}
});
}
}
请注意,这只是一个解决方法!请关注此 GitHub 问题以获取未来的更新。感谢Victor Savkin提供的解决方案!
"['../faq']"
作为值,否则它会尝试跳转到/faq/faq/#anchor,而不是/faq/#anchor。这样做是正确的吗?还是有更优雅的方法来引用routerlink中的当前页面?另外,document.querySelector("#" + tree.fragment);
给我返回了一个无效选择器错误。你确定这是正确的吗?谢谢。 - Maurice<a [routerLink]="['/faq']" fragment="section6">
工作? - Junior Mayhé有点晚了,但这是我找到的一个可行的答案:
<a [routerLink]="['/path']" fragment="test" (click)="onAnchorClick()">Anchor</a>
并且在组件中:
constructor( private route: ActivatedRoute, private router: Router ) {}
onAnchorClick ( ) {
this.route.fragment.subscribe ( f => {
const element = document.querySelector ( "#" + f )
if ( element ) element.scrollIntoView ( element )
});
}
以上情况在您着陆带有锚点的页面时不会自动滚动到视图,因此我在我的ngInit中使用了上述解决方案,以便它也可以处理这种情况:ngOnInit() {
this.router.events.subscribe(s => {
if (s instanceof NavigationEnd) {
const tree = this.router.parseUrl(this.router.url);
if (tree.fragment) {
const element = document.querySelector("#" + tree.fragment);
if (element) { element.scrollIntoView(element); }
}
}
});
}
确保在你的组件开始时导入Router、ActivatedRoute和NavigationEnd,然后一切都应该顺利进行。
document.querySelector("#" + f)
给我报错了,因为它需要一个选择器,而不是一个字符串。 - Mauriceelement.scrollIntoView()
(不需要将 element
传递给函数)。如果想要平滑滚动,请使用以下代码:element.scrollIntoView({block: "end", behavior: "smooth"})
。 - Mr. B.onAnchorClick()
中,我们必须传递一个布尔值给scrollIntoView
: if (element) { element.scrollIntoView(true); }
。现在我可以点击两次相同的链接并且滚动起作用了。 - Junior Mayhé之前的答案都对我没用。最后一招,我尝试了在我的模板中:
<a (click)="onClick()">From Here</a>
<div id='foobar'>To Here</div>
在我的 .ts 文件中使用以下代码:
onClick(){
let x = document.querySelector("#foobar");
if (x){
x.scrollIntoView();
}
}
对于内部链接,它按预期工作。实际上,这并不使用锚标签,因此完全不会触及URL。
x.scrollIntoView({ behavior: 'smooth', })
的翻译:使用平滑滚动效果更佳 ;) - Nevada如果在URL中添加这些元素ID不重要,您应该考虑查看此链接:
// html
// add (click) event on element
<a (click)="scroll({{any-element-id}})">Scroll</a>
// in ts file, do this
scroll(sectionId) {
let element = document.getElementById(sectionId);
if(element) {
element.scrollIntoView(); // scroll to a particular element
}
}
<a [fragment]="test1" [routerLink]="['./']">Go to Test 1 section</a>
<section id="test1">...</section>
<section id="test2">...</section>
在ts文件中:
export class PageComponent implements AfterViewInit, OnDestroy {
private destroy$$ = new Subject();
private fragment$$ = new BehaviorSubject<string | null>(null);
private fragment$ = this.fragment$$.asObservable();
constructor(private route: ActivatedRoute) {
this.route.fragment.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
this.fragment$$.next(fragment);
});
}
public ngAfterViewInit(): void {
this.fragment$.pipe(takeUntil(this.destroy$$)).subscribe(fragment => {
if (!!fragment) {
document.querySelector('#' + fragment).scrollIntoView();
}
});
}
public ngOnDestroy(): void {
this.destroy$$.next();
this.destroy$$.complete();
}
}
在app-routing.module.ts
中使用此代码:
@NgModule({
imports: [RouterModule.forRoot(routes, {
useHash: true,
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
scrollOffset: [0, 64]
})],
exports: [RouterModule]
})
<a href="#/users/123#userInfo">
之前提供的解决方案对我没有用,但下面这个就起作用了:
首先,在ngAfterViewChecked()中为MyAppComponent
准备自动滚动…
import { Component, OnInit, AfterViewChecked } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
@Component( {
[...]
} )
export class MyAppComponent implements OnInit, AfterViewChecked {
private scrollExecuted: boolean = false;
constructor( private activatedRoute: ActivatedRoute ) {}
ngAfterViewChecked() {
if ( !this.scrollExecuted ) {
let routeFragmentSubscription: Subscription;
// Automatic scroll
routeFragmentSubscription =
this.activatedRoute.fragment
.subscribe( fragment => {
if ( fragment ) {
let element = document.getElementById( fragment );
if ( element ) {
element.scrollIntoView();
this.scrollExecuted = true;
// Free resources
setTimeout(
() => {
console.log( 'routeFragmentSubscription unsubscribe' );
routeFragmentSubscription.unsubscribe();
}, 1000 );
}
}
} );
}
}
}
然后,导航到my-app-route
并发送prodID
哈希标签。
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component( {
[...]
} )
export class MyOtherComponent {
constructor( private router: Router ) {}
gotoHashtag( prodID: string ) {
this.router.navigate( [ '/my-app-route' ], { fragment: prodID } );
}
}
在 Angular 版本小于 6.1 的情况下,其他答案都可以使用。但如果您拥有最新版本,则不需要执行这些丑陋的操作,因为 Angular 已经修复了该问题。
所有你需要做的就是在 RouterModule.forRoot
方法的第二个参数选项中设置scrollOffset
。
@NgModule({
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
scrollOffset: [0, 64] // [x, y]
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
123
),假设路由路径需要一个参数,如{ path: 'users/:id', ....}
。 - Günter Zöchbauer01
或100
不是有效的 CSS 选择器。你可能希望添加一个字母或其他内容来使其成为有效选择器。因此,你仍然可以将01
作为片段传递,但id
需要像d01
这样的东西,这样document.querySelector('#d'+id)
就能匹配了。 - pop