In Angular 4 如何重新注入从模板创建的组件

In Angular 4 How to re-inject a component created from the template

我正在使用 Angular 4 构建应用程序,我想使用自定义结构指令删除并重新插入 DOM 元素。

带有自定义结构指令的模板如下所示。

    <div class="header-nav" *showIn="'xs'">
        <a class="nav-link nav-icon"
           [class.active]="isSearchFormOpen | async"
           (click)="toggleSearchForm()">
            <clr-icon
                [attr.shape]="(isSearchFormOpen | async) ? 'zoom-out' : 'zoom-in'">
            </clr-icon>
        </a>
    </div>

和 'showIn' 结构指令执行以下操作。

@Input() set showIn(target: string) {
    console.log(this.templateRef);
    this.breakPoint.subscribe((breakPoint) => {
        if (target === breakPoint) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.remove();
        }
    })
};

'breakPoint' 是每次调整 window 大小时返回的值,根据该值是否与指令的输入值匹配,我想注入或弹出 DOM元素.

问题是当元素从视图中移除后再次注入时,注入 'clr-icon' 元素时没有我最初设置的属性绑定 ('[attr.shape]=" (isSearchFormOpen | async) ? 'zoom-out' : 'zoom-in'"),使元素本身不可见。只有在我明确单击 window 内部后,此属性绑定才会启动,使元素再次可见。

如何在不丢失所有 属性 和属性绑定的情况下重新插入 DOM 元素?

您必须创建一个嵌入式视图并存储对它的引用。然后只需插入或分离它。像这样:

view = this.templateRef.createEmbeddedView(null);

@Input() set showIn(target: string) {
    console.log(this.templateRef);
    this.breakPoint.subscribe((breakPoint) => {
        if (target === breakPoint) {
            this.viewContainer.insert(this.view);
        } else {
            this.viewContainer.detach();
        }
    })
};

此解决方案的性能更高,因为它只是 attaches/removes 视图 DOM 节点到主机 DOM 节点,而不是每次都创建和销毁视图 destroys/creates DOM 个与视图相关的节点。