在Angular 4中单击时滚动到元素


99

我希望能够在按下按钮时滚动到目标。我在想这样的事情。

<button (click)="scroll(#target)">Button</button>

和我component.ts的方法一样。

scroll(element) {
    window.scrollTo(element.yPosition)
}

我知道上面的代码无效,只是为了表明我的想法。我刚刚开始学习Angular 4,但以前没有Angular的经验。我一直在寻找类似的东西,但所有示例都在AngularJs中进行,这与Angular 4截然不同


1
您的语法没有问题,但是您需要定义什么是#target。
wannadream

1
所以这应该工作吗?当我使用任意数字并在函数中调用window.scrollTo(500)时,没有任何反应。我当时认为该元素将是HTMLElement

是的,但是#target是什么,Angular不会解决它?您可以先测试不带参数的scroll()。
wannadream

是的,我在按钮和window.scrollTo(

2
但是,当我在构造函数中以500ms的延迟执行window.scrollTo(

Answers:


150

您可以这样做:

<button (click)="scroll(target)"></button>
<div #target>Your target</div>

然后在您的组件中:

scroll(el: HTMLElement) {
    el.scrollIntoView();
}

编辑:我看到评论说,由于元素未定义,这不再起作用。我在Angular 7中创建了一个StackBlitz示例,它仍然有效。有人可以提供一个不起作用的示例吗?


由于某种原因,运行确切的代码对我没有任何帮助。即使是硬编码的window.scrollTo(

1
@ N15M0_jk是的,还有一个可以通过其他选项传递的对象,具体取决于您的需求。developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView
Frank Modica

1
@Anthony它允许您引用要传递给scroll组件上函数的元素。请注意,click事件将调用scroll(target)。如果您想从组件内部访问元素而不必传递元素,则可以使用@ViewChild
弗兰克·莫迪卡

2
现在对我来说很好。但是在我犯了一个愚蠢的错误并用它id="target"代替之前#target,它给了我“ el is undefined error”!
yashthakkar1173

1
我相信,如果带有的元素#target位于内*ngIf,则会发生未定义的错误,但是如果您@ViewChild在@abbastec
壮观

46

实际上,没有使用setTimeoutrequestAnimationFrame或jQuery 的纯JavaScript方法即可完成此操作。

简而言之,在scrollView中找到要滚​​动到的元素,然后使用scrollIntoView

el.scrollIntoView({behavior:"smooth"});

这是一个笨拙的人


2
答案有2种不同的方式:1.这是动画平滑滚动,而不是跳跃。2.此答案不会滚动窗口,而是在窗口内移动滚动视图。例如,如果您在窗口中有一个水平滚动视图。请查看plunkr示例。
乔恩(Jon)

1
scrollIntoView的scrollIntoViewOptions(作为参数的对象)目前仅与Firefox兼容。
赫苏斯·富恩特斯

适用于Chrome和Firefox,但不适用于Safari。
Yamashiro Rion

45

这是我使用Angular 4的方法。

模板

<div class="col-xs-12 col-md-3">
  <h2>Categories</h2>
  <div class="cat-list-body">
    <div class="cat-item" *ngFor="let cat of web.menu | async">
      <label (click)="scroll('cat-'+cat.category_id)">{{cat.category_name}}</label>
    </div>
  </div>
</div>

将此功能添加到组件。

scroll(id) {
  console.log(`scrolling to ${id}`);
  let el = document.getElementById(id);
  el.scrollIntoView();
}

您尚未在模板中设置elementRefs或HTML ID。您要滚动到的'cat-'+ cat.category_id元素到底在哪里?
Keegan

1
这是一个更好的答案。您可以将滚动条放置到另一个组件。
Dale Nguyen,

这应该是公认的答案。为Angular 9工作
16

30

在Angular 7中完美工作

的HTML

<button (click)="scroll(target)">Click to scroll</button>
<div #target>Your target</div>

在组件中

  scroll(el: HTMLElement) {
    el.scrollIntoView({behavior: 'smooth'});
  }

2
{行为:“平稳”}的奖金
Squapl食谱,

它对我
有用

如果#target在按钮后定义,则此方法将不起作用,例如,如果您具有浮动标题,则这是相关的……
乔纳森

21

乔恩(Jon)有正确的答案,这可以在我的5号和6号角项目中使用。

如果要单击以从导航栏平滑滚动到页脚:

<button (click)="scrollTo('.footer')">ScrolltoFooter</button>
<footer class="footer">some code</footer>

scrollTo(className: string):void {
   const elementList = document.querySelectorAll('.' + className);
   const element = elementList[0] as HTMLElement;
   element.scrollIntoView({ behavior: 'smooth' });
}

因为我想从页脚滚动回到页眉,所以我创建了一个服务,该函数位于该服务中,并将其注入到导航栏和页脚组件中,并在需要时传递给“页眉”或“页脚”。只要记住要为组件声明实际使用的类名:

<app-footer class="footer"></app-footer>

15

在Angular中执行此操作的另一种方法是:

标记:

<textarea #inputMessage></textarea>

添加ViewChild()属性:

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

使用scrollIntoView()功能滚动到组件内部所需的任何位置:

this.inputMessageRef.nativeElement.scrollIntoView();

10

您可以使用下面的代码块滚动到视图上的任何元素ref。请注意,目标(elementref id)可以位于任何有效的html标记上。

在视图上(html文件)

<div id="target"> </div>
<button (click)="scroll()">Button</button>
 

  

.ts文件上

scroll() {
   document.querySelector('#target').scrollIntoView({ behavior: 'smooth', block: 'center' });
}

7

您可以通过使用对角度DOM元素的引用来实现此目的,如下所示:

这是stackblitz中的例子

组件模板:

<div class="other-content">
      Other content
      <button (click)="element.scrollIntoView({ behavior: 'smooth', block: 'center' })">
        Click to scroll
      </button>
    </div>
    <div id="content" #element>
      Some text to scroll
</div>

6

在Angular中,您可以使用ViewChildElementRef:为您的HTML元素提供参考

<div #myDiv > 

在组件内部:

import { ViewChild, ElementRef } from '@angular/core';
@ViewChild('myDiv') myDivRef: ElementRef;

您可以this.myDivRef.nativeElement用来了解您的元素


这是一个很好的解决方案,但问题是它仅在我重新加载选项卡时才有效,但不能与routerLink一起使用。这个问题有什么解决办法吗?
Ahsan

-8

通过使用jQuery查找元素(例如document.getElementById(...))并使用.focus()调用,我已经完成了您所要求的操作。


3
使用Angular时真的需要jQuery吗?像Angular这样的感觉就足够了

并非100%不确定,但是我所处的环境尚未经过Angular2的验证和重构,因此我在Angular中寻找解决方案的努力并没有太过努力,只是尝试了一些我知道可以使用的方法。
肯尼斯·所罗门

8
您不应该使用Jquery和Angular
Stefdelec

2
是的,我学到了很多东西,每个人都说我不应该使用jQuery。您并不是说别人没有在您上方发表任何评论。
肯尼斯·所罗门

为您的谦卑而投票。我想补充一点,jQuery答案对于那些正在向SPA框架过渡的人来说具有一定的价值。通过展示我们过去的做法,并查看评论,推荐其他解决方案。
B2K

-17

您可以使用jquery做到这一点:

ts代码:

    scrollTOElement = (element, offsetParam?, speedParam?) => {
    const toElement = $(element);
    const focusElement = $(element);
    const offset = offsetParam * 1 || 200;
    const speed = speedParam * 1 || 500;
    $('html, body').animate({
      scrollTop: toElement.offset().top + offset
    }, speed);
    if (focusElement) {
      $(focusElement).focus();
    }
  }

html代码:

<button (click)="scrollTOElement('#elementTo',500,3000)">Scroll</button>

将其应用于您要滚动的元素:

<div id="elementTo">some content</div>

是一个stackblitz示例。


1
除非此操作要求TypeScript解决方案不能与过时的框架一起使用(投反对票)

这是打字稿解决方案。
Gns

1
您已经错过了我的观点,您的答案使用的是jQuery(我可能以最低效的方式添加),而不是简单地使用ES *。您的常量也不会声明其类型。这只是一个不好的例子,使用jQuery的逻辑不好,这不是要问的。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.