43

我正在尝试对同一页面上的锚元素进行简单的滚动。基本上,该人单击“尝试”按钮,然后滚动到页面下方的区域,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>
4

9 回答 9

54

对于 Angular 6+,您可以使用:

  1. 在您的路由模块中:

     imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled'})]
    
  2. 然后在你的组件 html

     <a (click)="onClick('AnchorId')">Click me!</a>
     <a (click)="onClick('OtherAnchorId')">Click me, too!</a>
     ...
     <div id="AnchorId">...</div>
     ...
     <div id="OtherAnchorId">...</div>
    
  3. 然后在你的组件 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);
      }
    }
    
于 2019-11-03T21:35:13.683 回答
28

I think it's more simple solution :

In your HTML :

<a [routerLink]="['/']" fragment="login"></a>

In your typescript :

ngOnInit() {
 this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
}

ngAfterViewChecked(): void {
  try {
      if(this.fragment) {
          document.querySelector('#' + this.fragment).scrollIntoView();
      }
  } catch (e) { }
}
于 2017-11-29T16:38:48.573 回答
27

自动滚动

从 Angular v6 开始,anchorScrolling有了RouterModule. 您可以在模块的导入中设置它:

imports: [
  ...,
  RouterModule.forRoot(routes, {anchorScrolling: 'enabled'})

这样,Angular 将自动滚动到具有给定片段 id 的元素。

⚠️ 但是,这在异步加载数据时不起作用,请参阅这个Github issue。⚠️


手动滚动

还不能通过平滑滚动RouterModule,但您可以手动进行:

1)获取您的目标,例如ViewChild

@ViewChild('pageInfo') pageInfo: ElementRef; 

2 )调用scrollIntoViewnativeElement

const targetElement = this.pageInfo.nativeElement
targetElement.scrollIntoView({behavior: "smooth"})
于 2018-09-09T03:07:39.680 回答
6

Moerdern 一条线解决方案:

export class Component implements AfterViewInit {

  constructor(
    private viewportScroller: ViewportScroller
  ) { }

  ngAfterViewInit(): void {
    this.route.fragment.pipe(
      first()
    ).subscribe(fragment => this.viewportScroller.scrollToAnchor(fragment));
  }
}
于 2020-10-03T14:39:31.633 回答
4

所以,我只花了大约一个小时使用最新的 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>

现在,我可以访问不同的锚点,并在我回溯/前进历史时查看滚动。希望它可以帮助某人!

于 2020-06-21T01:45:07.353 回答
3

AfterViewCheck()每次ChangeDetection触发时都会调用,所以这是一个不好的解决方案。

使用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();
}
于 2018-12-07T14:50:45.700 回答
3

使用 Angular 4,使用锚点到同一页面可能会遇到一些问题。

我用这种方式解决了

ng2-page-scroll

安装

npm install ng2-page-scroll --save

导入你的 app.module.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">
于 2017-10-05T13:58:19.193 回答
1

最后,在 Angular 7 中为我工作:

html:

<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' });
  }
于 2020-01-29T10:30:18.817 回答
0

这是一个更详细的示例,可以添加到上面 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 :)

于 2019-08-07T18:47:22.127 回答