Angular2的Hashtag路由到锚点不能移动页面

12

我使用以下文章来学习如何向URL添加片段:

Angular2 Routing with Hashtag to page anchor

虽然片段被成功添加,但页面没有滚动到相应的锚点。我尝试在目标

上使用nameid属性,但似乎都不起作用。

我正在使用 Angular 版本 2.0.0-rc.3 和路由器版本 3.0.0-alpha.6。

谢谢!

<a [routerLink]="[]" fragment="destination">Go TO DIV</a>

<div id='destination'>
    <h2>Destination</h2>
</div>

两个元素之间有足够的空间,以便判断页面是否实际移动。

并且如之前所述,url正确地将#destination添加到自身。


请添加展示您尝试过的代码。提供一个Plunker以便复现将会很有帮助。 - Günter Zöchbauer
我添加了我正在尝试的当前方法,但我也尝试使用链接帖子中的this._router.navigate( ['/somepath', id ], {fragment: 'test'});示例在函数中更改它。 - jipson
请尝试使用实际的路由路径,例如 <a [routerLink]="['../currentroute']" fragment="destination">转到DIV</a> - Günter Zöchbauer
当前路由是/docs,所以我尝试使用<a [routerLink]="['../docs']" fragment="destination">前往DIV</a>,它仍会生成正确的URL。然而,它仍然没有移动。 - jipson
抱歉,我已经没有更多的想法了。 - Günter Zöchbauer
7个回答

15

一种解决方法是在您的组件中编写一个函数,将location.hash设置为要导航到的div的ID。

<a (click)="goTo('destination')">Go TO DIV</a>

<div id='destination'>
    <h2>Destination</h2>
</div>

然后在你的组件中:

goTo(location: string): void {
    window.location.hash = location;
}

5
我想在这里添加一条注释。它只设置哈希一次,因此如果哈希已经包含在页面中,并且您单击相同的锚链接,则不会滚动到目标位置。但是,如果在设置之前清除哈希,则可以正常工作 -> window.location.hash = ''; window.location.hash = location; - Samurai Girl
我尝试过这个,它能工作,但是目标上面的所有内容都消失了。 - JonathanPeel
1
比使用路由器要简单得多。我理解这是因为路由和所有SPA的东西都很复杂,但锚链接是如此基本的功能。 - Gilles

3
这是一个对我很有效的非常简单的解决方案:
在组件中,添加这个方法:
navigateTo(location: string): void {
// location will be a valid CSS ID selector; i.e. it should be preceded with '#'
window.location.hash = location;
setTimeout(() => {
    document.querySelector(location).parentElement.scrollIntoView();
  });
}

在页面上,<a>标签将如下所示:

<a (click)="navigateTo('#destination')">Destination</a>

目前正在使用Angular 4 / CLI。这是最好的解决方案。谢谢!同时,它是最简单且代码量最少的可行解决方案。 - Mindsect Team

2

这对我很有帮助:

首先,在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 } );
  }

}

2
这个解决方法应该可以解决问题。
<div [routerLink]="[]" fragment="destination">
  <a href="#destination">Go TO DIV</a>
</div>

1
谢谢,不需要TypeScript / JavaScript!这些东西不应该那么难。有时感觉正在重新发明轮子。 - Oliver
它在除根路径以外的任何路径上都无法生成正确的URL。 - Daniel Kucal

2

在看过这里提供的所有解决方案后,我决定使用一个小而简单的指令。下面是我的最终选择:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({ selector: '[appAnchorTo]' })
export class AnchorToDirective {
  @Input() target: string;

  constructor(el: ElementRef) { el.nativeElement.style.cursor = 'pointer'; }

  @HostListener('click', ['$event'])
  onClick() { document.querySelector(this.target).scrollIntoView(); }
}

这个想法是创建一个灵活的东西,可以附加到页面上的任何元素。

用法:

<a appAnchorTo target="#my-link">My Insights</a>
<div appAnchorTo target="#my-other-link">My Customers</div>

不要忘记在其中一个模块上声明该指令:

@NgModule({
    ...,
    declarations: [
        ...,
        AnchorToDirective,
    ]
})

1

0

我在npm上找到了一个非常有用的插件 - ngx-scroll-to,它对我非常有效。然而,它是为Angular 4+设计的,但也许有人会发现这个答案有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接