如何获得 Angular 5 组件元素的位置?

Posted

技术标签:

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

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

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

@ViewChild('table')
tableElement: ElementRef

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

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

【问题讨论】:

【参考方案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');
            
        );
    

【讨论】:

以上是关于如何获得 Angular 5 组件元素的位置?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 5:从组件访问元素内部 html 以获取动态生成的元素

如何在此文件夹中创建一个全新的 Angular 组件?为啥我使用 Angular CLI 获得此错误消息?

Angular 2 @ViewChild 返回未定义

Angular 如何测试需要位置的组件

Angular 通过另一个组件获得新的范围

如何将 DOM 附加到 Angular 2 组件并仍然获得封装样式