我正在尝试使用 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的相关实例。
答案 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);
}
如果仅关心视口尺寸的更改,则无需使用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);
}