【问题标题】:How can I get an Angular 5 component element's position?如何获得 Angular 5 组件元素的位置?
【发布时间】:2018-09-13 03:35:01
【问题描述】:

在一个 Angular 5 组件中,我有一个 table,我需要创建一些东西,比如在多个 td 之上叠加多个 div .获得这些 td 在表格中的位置以便我可以定位其他元素的最佳方法是什么?

我目前正在尝试使用类似的东西

@ViewChild('table')
tableElement: ElementRef

ngAfterViewChecked() {
    this.tableElement.nativeElement.getElementsByClassName('cell')
    // ...
}

但我这样做是冒着一些奇怪的无限循环的风险。例如,有没有办法知道特定元素被“重绘”了?

【问题讨论】:

    标签: angular components render angular5


    【解决方案1】:

    “无限”循环是正常的,因为您在 AfterViewChecked 生命周期挂钩中运行该函数。

    按设计:AfterViewChecked Lifecycle hook that is called after every check of a component's view.

    我会使用 getBoundingClientRect 来获取顶部、底部、宽度、高度等。const domRect = element.getBoundingClientRect(); https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect,但我不确定我是否理解在哪种情况下要运行 getElement。 “重绘”是什么意思?如果数据是动态的,你可以尝试在 promise 解决后获取位置。

    【讨论】:

    • 我想要一个事件或类似的东西,在绘制表格后调用 get 并且我可以获得每个元素的位置,所以我可以以某种方式定位覆盖的 div。
    • 正如我在回答中提到的,如果表的数据来自后端,则在解决承诺时必须调用 getBoundingClientRect()。如果表格的数据在模板中被硬编码,那么 ngAfterViewInit() 应该没问题。它只被调用一次。
    【解决方案2】:

    据我了解,您希望相对于另一个元素(div)定位一个 html 元素(td)。这似乎是一个普通的 html 和 css 问题。

    您可以将这两个元素放在一个包含框中

    position: relative;
    

    您要放置在上面的 div 应该具有以下属性,以便它们与您的 td 重叠

    position: absolute;
    top: /*your top value*/;
    left: /*your left value*/;
    

    如果你真的想得到你的 td 的确切位置,那么你需要通过 Javascript 提取顶部、底部、右侧和左侧的位置。

        this.tableElement.nativeElement.getElementsByClassName('cell').getBoundingClientRect();
    

    【讨论】:

    • 我在定位DIV时没有TD的位置,所以不是CSS问题。
    • 您不需要 td 的位置来相应地定位 div。或者使用我在下面提到的选项。
    【解决方案3】:

    一种方法:合并来自调整大小事件和主题的流。如果您使用 http 获取数据而不是主题,则可以使用从那里已经拥有的相同 observable,例如 http.get(...).pipe(share())

    import {merge} from 'rxjs/observable/merge';
    import {fromEvent} from 'rxjs/observable/fromEvent';
    import {Subject} from 'rxjs/Subject};
    // ...
    tableChange$:Subject<void> = new Subject();
    
    ngOnInit() {
        merge(
             fromEvent(window, 'resize'),
             this.tableChange$
        ).subscribe(() => {
            this.tableElement.nativeElement.getElementsByClassName('cell')...
        }); // remember to unsubscribe this subscription at OnDestroy in real life
        this.tableChange$.next();
    }
    

    编辑:

    将这个问题转移到您将在这些 TD 中使用的组件可能是一种更简洁、更简单的解决方案。您可以使用ng-content 显示组件内的任何内容,并通过在构造函数中注入它来获取 elementRef。如果您仍然需要与父母交谈,请使用输出。

    【讨论】:

      【解决方案4】:

      这里提出的方法对我不起作用。相反,我使用了getBoundingClientRectwindow.innerHeight

      boundingRect,添加顶部和高度属性。如果小于window.innerHeight,则变为可见。

      此方法适用于任何框架 (afaik)。但这是一个 Angular 示例:

      import { ElementRef } from '@angular/core';
      
      class ExampleComponent {
          constructor(private el: ElementRef) {
              window.addEventListener('scroll', () => {
                  const rect = this.el.nativeElement.getBoundingClientRect();
      
                  if (rect.top + rect.height < window.innerHeight) {
                      console.log('component is visible');
                  }
              });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-12
        • 2017-07-23
        • 2015-01-04
        • 2019-09-02
        • 2012-06-29
        • 2017-07-05
        • 1970-01-01
        • 2016-05-13
        相关资源
        最近更新 更多