【问题标题】:Scroll to element on click in Angular 4在Angular 4中单击时滚动到元素
【发布时间】:2017-10-12 05:38:23
【问题描述】:

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

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

在我的component.ts 中,类似的方法。

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

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

【问题讨论】:

  • 你的语法没有问题,但你需要定义什么是#target。
  • 所以这应该有效吗?当我在函数中使用任意数字并调用 window.scrollTo(500) 时,什么也没有发生。我在想那个元素会是一个 HTMLElement
  • 对,但是,#target是什么,Angular不会解决它?你可以先不带参数测试scroll()。
  • 是的,我在按钮中尝试了 (click)="scroll()" 并在组件中尝试了 window.scrollTo(0, 500) 但没有任何反应
  • 但是当我在构造函数中以 500 毫秒的延迟执行 window.scrollTo(0, 500) 时,它可以工作

标签: javascript html angular typescript


【解决方案1】:

我需要做这个技巧,可能是因为我使用了自定义 HTML 元素。如果我不这样做, target in onItemAmounterClick 不会有 scrollIntoView 方法

.html

<div *ngFor"...">
      <my-component #target (click)="clicked(target)"></my-component>
</div>

.ts

onItemAmounterClick(target){
  target.__ngContext__[0].scrollIntoView({behavior: 'smooth'});
}

【讨论】:

    【解决方案2】:

    在 Angular 7 中完美运行

    HTML

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

    在组件中

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

    【讨论】:

    • 对 {behavior: 'smooth'} 的奖励
    • 它对我有用.. 特别感谢 {behavior: 'smooth'}
    • 如果在按钮之后定义#target,这将不起作用,例如,如果您有一个浮动标题,这将是相关的......
    • 太棒了,对我也有用,感谢平滑滚动的好处
    • 确认在 Angular 12 中按预期工作。干得好!
    【解决方案3】:

    在 Angular 中,您可以使用 ViewChildElementRef: 给你的 HTML 元素一个 ref

    <div #myDiv > 
    

    在你的组件内部:

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

    您可以使用this.myDivRef.nativeElement 访问您的元素

    【讨论】:

    • 这是一个很好的解决方案,但问题是它仅在我重新加载选项卡时才有效,而不是使用 routerLink。这个问题有什么解决办法吗?
    • 如何使用class
    • @Ahsan 你可能想试试 ngAfterViewInit 或 ngAfterViewChecked。
    【解决方案4】:

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

    【讨论】:

    • 在使用 Angular 时真的需要 jQuery 吗?感觉 Angular 应该够用了
    • 不是 100% 确定,但我所处的环境尚未针对 Angular2 进行验证和重构,因此我没有在 Angular 中搜索太多解决方案,而是选择了我知道我会拥有的东西访问。
    • 你不应该使用 Jquery 和 Angular
    • 是的,是的,我学到了很多东西,每个人都认为我不应该使用 jQuery。你没有说任何其他人没有在你上面评论过的东西。
    • 为你的谦逊点赞。我想补充一点,jQuery 答案对于那些正在过渡到 SPA 框架的人来说有一些价值。通过展示我们过去是如何做到这一点的,并看到 cmets 推荐其他解决方案。
    【解决方案5】:

    这是我使用 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 元素到底在哪里?
    • 这是一个更好的答案。您可以将滚动条放到另一个组件上。
    • 这应该是公认的答案。为 Angular 9 工作。
    • 在 Angular 11 中工作
    • 嘿@Keegan,在这种情况下,您可以假设web.menu 是一个类别数组。
    【解决方案6】:

    在 Angular 中的另一种方法:

    标记:

    <textarea #inputMessage></textarea>
    

    添加ViewChild()属性:

    @ViewChild('inputMessage')
    inputMessageRef: ElementRef;
    

    使用scrollIntoView() 函数在组件内任意滚动:

    this.inputMessageRef.nativeElement.scrollIntoView();
    

    【讨论】:

      【解决方案7】:

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

      在视图上(html文件)

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

      .ts 文件上,

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

      【讨论】:

        【解决方案8】:

        您可以通过使用对 Angular 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>
        

        【讨论】:

          【解决方案9】:

          你可以这样做:

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

          然后在你的组件中:

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

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

          【讨论】:

          • @N15M0_jk 是的,您还可以使用其他选项传入一个对象,具体取决于您的需要。 developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
          • @Anthony 它允许您引用要传递给组件上的scroll 函数的元素。注意点击事件调用scroll(target)。如果您想从组件内部访问元素而不必传入元素,您可以使用@ViewChild
          • 以下链接将是正确的解决方案stackoverflow.com/questions/47616843/…
          • 我现在可以正常使用了。但在我犯了一个愚蠢的错误并使用id="target" 而不是#target 之前它给了我“el is undefined error”!
          • 我相信如果带有#target 的元素在*ngIf 内,则会发生未定义的错误,但如果您在来自@abbastec 的链接中使用@ViewChild 方法,它应该可以工作
          【解决方案10】:

          您可以使用 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>
          

          Here 是一个 stackblitz 示例。

          【讨论】:

          • 除了这个操作要求 TypeScript 解决方案不能使用过时的框架(否决)
          • 这是打字稿解决方案。
          • 你错过了我的意思,你的答案使用了 jQuery(我可能以最低效的方式添加)而不是简单地使用 ES*。你的常量也没有声明它们的类型。这只是一个糟糕的例子,使用 jQuery 的逻辑很糟糕,这不是所要求的。
          【解决方案11】:

          Jon 有正确的答案,这适用于我的 Angular 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>
          

          【讨论】:

            【解决方案12】:

            实际上有一种纯 javascript 方法可以在不使用 setTimeoutrequestAnimationFrame 或 jQuery 的情况下完成此操作。

            简单来说就是在scrollView中找到你想要滚动到的元素,使用scrollIntoView

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

            这是plunkr

            【讨论】:

            • 这个答案不同的两种方式: 1. 这是动画平滑滚动,而不是跳跃。 2.此答案不滚动窗口,而是在窗口内移动滚动视图。例如,如果您在窗口中有一个水平滚动视图。查看 plunkr 以获取示例。
            • scrollIntoView 的 scrollIntoViewOptions(作为参数的对象)目前只兼容 Firefox。
            • 适用于 Chrome 和 Firefox,但不适用于 Safari。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-07-03
            • 2017-01-16
            • 2018-01-26
            • 1970-01-01
            • 2018-08-25
            • 2014-04-29
            • 2018-01-08
            相关资源
            最近更新 更多