gpt4 book ai didi

angular - nativeElement.getBoundingClientRect() 在 Angular 测试中总是返回 0

转载 作者:太空宇宙 更新时间:2023-11-03 15:38:31 32 4
gpt4 key购买 nike

我有一个相对于 nativeElement.getBoundingClientRect() 定位自身的 Angular 组件 (5.2)另一个元素的输出。

在测试中,我创建了一个带有样式的包装器组件来模拟定位元素,但是返回的是 ClientRect始终全为零。

有没有办法让 Angular 实际在 DOM 中定位我的元素?

为了说明,这是我的 TestComponent .内部 <popup>组件将使用 anchor.nativeElement.getBoundingClientRect() 计算它的固定位置.

我认为这不相关,但我正在使用 Jest 来执行测试。

我已经尝试过没有 async() .

@Component({
selector: 'test',
styles: [`
:host {
width: 1000px;
height: 1000px;
display: flex;
justify-content: center;
align-content: center;
}
`],
template: `
<button #button></button>
<popup [anchor]="button">
<div id="helloWorld">hello world</div>
</popup>
`
})
class TestComponent {
@ViewChild('button')
public buttonElement: ElementRef;
}

describe('test', () => {
let fixture;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
imports: [PopupModule]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
});
}));
it('should be positioned', () => {
const button = fixture.componentInstance.buttonElement.nativeElement;

// Either of these always fail, because the button is not positioned.
// I have also tried using fixed positioning of the button.

// this will fail
expect(button.getBoundingClientRect().top).not.toEqual(0);

// this will fail, too
return fixture.whenRenderingDone().then(() => {
expect(button.getBoundingClientRect().top).not.toEqual(0);
});
});
});

最佳答案

长话短说:

您只需要在 ngAfterViewInit() Hook 中使用 ElementRef 类型的 nativeElement,您的测试将“看到”DOM 中的元素。

长读:

.getBoundingClientRect() 只有在元素已呈现并存在于 DOM 中时才会起作用。今天,当我尝试访问被单击的元素时,我遇到了这种情况,并且使用 [routerLink] 它被路由器操作动态重新呈现 - 我无法在视觉上识别这种行为。它导致这个元素消失,并且不能有任何测量。接下来,在 ClientRect 中渲染了一些类似的元素,但为 0,0,0,0。

因此,如果您使用一些元素的动态重新呈现 - 如菜单或其他元素,您的 element.getBoundingClientRect() 将仅在元素消失时返回 0,0,0,0,重新渲染,或在“ Action 时间”(点击等)在 DOM 中不存在,就像您的情况一样。

因此您需要等待它被重新渲染和接下来 - 您可以通过 .getBoundingClientRect() 获得它的测量值。对于 @ViewChild() 最好的等待方式是 ngAfterViewInit() Hook ,您可以在其中访问 nativeElement(作为最佳方式)。此外 - 还有一些技巧,例如:

private elementInited$ = new Subject();
public desiredElement: ElementRef;
@ViewChild('someElemRef') set setElementRef(el: ElementRef) {
if (!!el) {
this.desiredElement= el;
this.elementInited$.next();
}
}

ngOnInit() {
this.elementInited$.subscribe((inited) => {
// do stuff with nativeElement
const values = this.desiredElement.nativeElement.getBoundingClientRect() // <== works!
})
}

但这太棘手了:)

此外,等待元素的一个好方法是 @Directive()。使用指令,您可以以“Angular 方式”正确地监听元素,并且仅当元素存在于 DOM 中时才会触发指令。

在 Devtools 中使用 Chrome 的渲染亮点也可能非常有帮助 - 只需打开 devtools 菜单 - 更多工具 > 渲染 > Paint flashing 复选框有助于识别哪些元素重新渲染。

关于angular - nativeElement.getBoundingClientRect() 在 Angular 测试中总是返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48894574/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com