AngularDart:渲染组件时会调用一个钩子吗?

时间:2019-11-29 20:28:43

标签: angular angular-dart

我正在尝试访问scrollHeight元素上的clientHeight<div>属性,以决定是否显示“查看更多”链接:

<div #clippedContainer class="clipped">
  <some-other-component></some-other-component>
  <a class="view-more" href="...">View more</a>
</div>
.clipped {
  max-height: 600px;
  overflow: hidden;
  position: relative;
}

.view-more {
  position: absolute;
  width: 100%;
  top: 550px;
  text-align: center;
  display: none;

  .displayed {
    display: block;
  }
}
@ViewChild('clippedContainer', read: Element)
set clippedContainer(Element container) {
  if (container.scrollHeight > container.clientHeight) {
    container.querySelector('.learn-more').classes.add('displayed');
  }
}

问题在于调用时scrollHeight为0,因为尚未显示组件。我尝试在scheduleMicrotaskngAfterViewInit中读取它,但是它仍然为0。我发现了一个hack,它等待一秒钟,让浏览器计算布局然后访问所需的属性:

Future.delayed(Duration(seconds: 1)).then(() {
  if (container.scrollHeight > container.clientHeight) {
    container.querySelector('.learn-more').classes.add('displayed');
  }
});

,但是这会在呈现的内容和链接出现之间引入不必要的延迟。有没有更好的方法来检测何时已计算布局并且scrollHeightclientHeight可用?

更新:我发现问题的部分原因是包含<div>的组件是由弹出框架动态构建的。看来ngAfterViewInit之类的钩子甚至在组件连接到DOM之前就已执行。

1 个答案:

答案 0 :(得分:0)

我发现了一种检测组件何时连接到DOM的方法,但是我并不喜欢这种方法,因为它非常复杂。希望有人能提出更好的解决方案。

class MyComponent {
  final NgZone _ngZone;
  final Element _hostElement;

  MyComponent(this._ngZone, this._hostElement);

  @ViewChild('clippedContainer', read: Element)
  Element container;

  void ngAfterViewInit() {
    final sub = _ngZone.onTurnStart.listen((_) {
      if (_hostElement.parent == null) return;
      sub.cancel();

      if (container.scrollHeight > container.clientHeight) {
        container.querySelector('.learn-more').classes.add('displayed');
      }
    });
  }
}