Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Angular 2正确检测计算样式属性中的更改?_Javascript_Css_Angular_Dom_Getcomputedstyle - Fatal编程技术网

Javascript 如何使用Angular 2正确检测计算样式属性中的更改?

Javascript 如何使用Angular 2正确检测计算样式属性中的更改?,javascript,css,angular,dom,getcomputedstyle,Javascript,Css,Angular,Dom,Getcomputedstyle,我已经创建了一个Angular 2应用程序,其中包含一个组件,我正试图相对于另一个组件定位该组件的HTML元素。为了计算精确的坐标,我需要知道浏览器渲染的元素的宽度和高度 我正在使用window.getComputedStyle(this.elementRef.nativeElement)获取这些属性。我注意到,在呈现页面时,属性会不断更改,直到页面呈现完成。为了了解任何更改并调整定位,我检查了组件的ngafterview checked方法中的值 但是,当渲染导致新的计算样式属性时,似乎不会调

我已经创建了一个Angular 2应用程序,其中包含一个组件,我正试图相对于另一个组件定位该组件的HTML元素。为了计算精确的坐标,我需要知道浏览器渲染的元素的宽度和高度

我正在使用
window.getComputedStyle(this.elementRef.nativeElement)
获取这些属性。我注意到,在呈现页面时,属性会不断更改,直到页面呈现完成。为了了解任何更改并调整定位,我检查了组件的
ngafterview checked
方法中的值

但是,当渲染导致新的计算样式属性时,似乎不会调用
ngAfterViewChecked
,因为我发现我的钩子不再被调用,即使计算样式属性仍在更改。我假设角度框架的设计不是为了检测这种变化

我的第一次尝试是实现
ngDoCheck
hook,但是似乎在一段时间之后,在computed style属性具有其最终值之前,也没有调用这个钩子。我假设我还没有完全理解何时要调用这个钩子

我最终发现,如果我在
ngafterview checked
中实现
setTimeout
函数,这将导致以后再次调用同一个钩子,即使我只传递一个伪函数,如:

setTimeout(() => {}, 500);
但坦率地说,我不明白为什么会这样有人能给我解释一下
setTimeout
ngafterview checked
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 ..]
 }

在香草JavaScript中,您可以使用:

并在DOM更改时触发您自己的函数

MutationObserver为开发人员提供了一种方法来对 大教堂。它被设计成一个替代品,用于替换在中定义的突变事件 DOM3事件规范

请参见上图以查看生命周期图。如果doCheck中的钩子不起作用,AfterViewChecked也不会起作用,因为doCheck启动AfterViewChecked

每次异步进程完成时,都会发生另一轮doCheck。这将调用AfterViewChecked,并调用updateView函数。SetTimout()是一个异步进程。我怀疑上面的代码会无限循环

我相信您想要的是让这里显示的父组件使用ngAfterViewChecked()并调用updateView()。我们将探讨这一主题

使两个组件协同工作的方法是让父组件可以在子组件之间传递更改,因为父组件是可以查看子组件中发生的事件的上下文


我个人使用的解决方案是一个EventEmitter,在未显示的组件中,在ngOnInit()函数中。它将通知父级它已初始化。然后,在父组件中,在发出的事件上进行函数调用,该事件告诉子组件您要在此处更新查看。

为什么在渲染导致新的计算样式属性时不调用ngAfterViewChecked?

Angular框架不会检测DOM元素的计算样式中的更改,至少在浏览器的渲染引擎导致更改时不会检测到。因此,在这种情况下不会调用
ngAfterViewChecked
钩子

为什么使用setTimeout时它会工作?

正如Michael Palmer在回答中所解释的那样,
setTimeout
会使Angular意识到一个可能导致更改的异步进程。因此,在执行超时功能后,将调用
ngAfterViewChecked
钩子。Angular不会尝试检查在
setTimeout
函数中到底做了什么,以及这是否会影响视图。显然,这将很难实现,可能不值得付出努力。相反,Angular调用
ngAfterViewChecked
hook,以防异步进程中发生影响视图的事情

聆听计算风格变化的角度方式是什么?


除了使用
setTimeout
来查看DOM元素计算样式的更改之外,似乎没有其他方法了。

对不起,我知道这并不能完全解决您的问题,但我希望它至少部分有用:)无论如何,谢谢,但我已经尝试了
observe(this.elementRef.nativeElement,{attributes:true})
这给了我多个回调,oldValue=null,newValue=undefined,仅此而已。我实际上怀疑是否会检测到DOM更改。我假设DOM不会改变,但只有getComputedStyle函数会计算不同的结果?!虽然这是一个有趣的选择,但经过一些研究,我得出结论,MutationObserver目前不支持观察计算样式属性。另请参见问题“是”,它不侦听计算的样式更改,作为CSS OM的一部分。什么是获得计算样式更改的解决方案?谢谢,我现在知道,任何异步进程都会导致调用
ngDoCheck
ngAfterViewChecked
,其中
setTimeout
是一种可能性,而不管调用什么函数
setTimeout
(即使在我的情况下没有)。顺便说一句,这不是一个无限循环,因为我不再在检测不到更改时发出
setTimeout
。然而,你剩下的答案似乎是基于误解