我创建了一个 Angular 2 应用程序,其中包含一个组件,我试图将其 HTML 元素相对于另一个组件定位。为了计算准确的坐标,我需要知道浏览器呈现的我自己元素的宽度和高度。
我window.getComputedStyle(this.elementRef.nativeElement)
用来获取这些属性。我注意到,在呈现页面时,属性会不断变化,直到页面呈现完成。为了了解任何更改并调整位置,我检查了ngAfterViewChecked
组件方法中的值。
但是,当渲染导致新的计算样式属性时,它似乎没有ngAfterViewChecked
被调用,因为我发现我的钩子不再被调用,即使计算的样式属性仍在变化。我假设 Angular 框架并非旨在检测这种变化。
我的第一次尝试是实现ngDoCheck
钩子,但似乎在一段时间后以及在计算的样式属性具有其最终值之前,也没有调用这个钩子。我假设我还没有完全理解这个钩子应该在什么时候被调用。
我终于发现,如果我在 中实现一个setTimeout
函数ngAfterViewChecked
,这会导致稍后再次调用同一个钩子,即使我只传递了一个虚拟函数,例如:
setTimeout(() => {}, 500);
但坦率地说,我不明白为什么会这样。有人可以向我解释一下 thesetTimeout
和ngAfterViewChecked
hook 之间的联系吗?
虽然这似乎是一个有点肮脏的解决方法:检测和处理计算样式属性变化的正确“角度”方法是什么?
代码摘录:
export class MyComponent implements OnInit, AfterViewChecked
{
private cssWidth: number;
private cssHeight: number;
constructor(private elementRef: ElementRef, private renderer: Renderer2)
{
}
ngAfterViewChecked()
{
console.log("ngAfterViewChecked");
this.updateView();
}
public updateView()
{
const sizeX = parseFloat(window.getComputedStyle(this.elementRef.nativeElement).width) || 0;
const sizeY = parseFloat(window.getComputedStyle(this.elementRef.nativeElement.height) || 0;
if (sizeX === this.cssWidth && sizeY === this.cssHeight) {
// no change
return;
}
console.log("Change detected!");
// TODO Does not work without this dummy timeout function (else no more changes detected) - why so??
setTimeout(() => {}, 500);
[.. doing the positioning here ..]
}