带有ResizeObserver的ViewContainerRef无法在成角度的

时间:2019-03-06 13:19:40

标签: angular angular7

我正在尝试使用 ComponentFactoryResolver 根据屏幕尺寸动态添加和删除组件。

@ViewChild('sidebarContainer', { read: ViewContainerRef }) sidebarContainer: ViewContainerRef;

_handleBodyResize() {
let self = this;
if (typeof ResizeObserver == 'undefined') return;

const obs = new ResizeObserver(entries => {
  let entry = entries[0];

  if ((entry.contentRect.width) < MOBILE_WIDTH) {
    if (this.deviceType !== DeviceType.mobile) {
      this.removeSidebar();

      this.deviceType = DeviceType.mobile;
    }
  } else {
    if (this.deviceType !== DeviceType.desktop) {
      this.addSidebar();

      this.deviceType = DeviceType.desktop;
    }
  };
});

removeSidebar() {
  this.sidebarContainer.clear();
  this.sidebarRef.destroy();
}

addSidebar() {
this.sidebarContainer.clear();
//_cfr is componentFactoryResolver
const compFactory = this._cfr.resolveComponentFactory(this.array[0]);

let comp = this.sidebarContainer.createComponent(compFactory);

this.sidebarRef = comp;
}

和HTML

<div class="sidebar-container">
<div #sidebarContainer>

</div>

只要正文的with从< 768px>= 768px并且不删除先前创建的sidebarContainer viewContainerRef似乎都无法保留引用并创建SidebarComponent的新实例。组件保存在 sidebarRef 中,并且事件 sidebarContainer.clear()方法不起作用

奇怪的是,如果我使用window.addEventListener('resize'...,它会起作用。

我是否不了解某些底层的 ResizeObserver 技术,并且有一种方法可以使其与 ResizeObserver

一起使用

更新

我忘了提及这一点,但是调整大小观察器中的代码会按时执行并适当地调用了两个函数。

else部分始终创建SidebarComponent的新实例并将其呈现到视图中,但是this.sidebarContainer.clear()this.sidebarRef.destroy不会删除先前创建的实例,即使在调试时,我也可以看到{{ 1}}和sidebarContainer不是未定义的,分别是ViewContainerRef和ComponentRef的相关实例。

2 个答案:

答案 0 :(得分:1)

Angular响应各种触发来执行更改检测。 DOM事件,ajax请求和计时器/可观察对象将触发Angular的更改检测。

窗口的resize事件是DOM事件的一个示例,它将触发更改检测。

据我所知,Angular的更改检测不是ResizeObserver自动触发的。因此,您需要使用ChangeDetectorRef.detectChanges()明确告诉Angular检测更改:

constructor(private changeDetector: ChangeDetectorRef) {}

ngAfterViewInit() {
  const obs = new ResizeObserver(entries => {
    // Perform updates in response to resize

    // Then tell Angular to detect changes
    this.changeDetector.detectChanges();
  });
  obs.observe(this.resizeDiv.nativeElement);
}

这里是StackBlitz example

如果仅关心视口尺寸的更改,则无需使用ResizeObserver。窗口resize事件将在所有浏览器中正常运行。

答案 1 :(得分:0)

ResizeObserver 不像窗口 DOM 事件那样被 NgZone 修补。但是,您可以像这样在 ResizeObserver 内显式运行 NgZone 回调:

constructor(private zone: NgZone) {}

ngAfterViewInit() {
  const obs = new ResizeObserver(entries => {
    this.zone.run(() => {
      // do what you got to do
    });
  });
  obs.observe(this.resizeDiv.nativeElement);
}

github issue