如何在 Angular 9 中动态删除组件?

Rod*_*rez 2 javascript typescript angular

我必须创建一个多选过滤器来接受要单击的多个选项值,以便优化后端某些获取 API 端点的响应。

\n

每当用户单击一个选项时,就会动态呈现一个“芯片”组件以感知用户:“嘿,您只需通过这个和那个过滤选项来过滤结果”

\n

在互联网上环顾四周,我发现了这个stackblitz

\n

在此代码示例中,我以某种方式理解了这一行:

\n
let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);\nlet childComponentRef = this.VCR.createComponent(componentFactory);\n
Run Code Online (Sandbox Code Playgroud)\n

我们将给定子组件的实例插入到ViewContainerRef. 找到一个类似这样的对象:

\n
_data: Object { renderElement: <!--  -->, componentView: undefined, viewContainer: {\xe2\x80\xa6}, \xe2\x80\xa6 }\n_elDef: Object { nodeIndex: 4, bindingIndex: 0, outputIndex: 1, \xe2\x80\xa6 }\n_embeddedViews: Array(5) [ {\xe2\x80\xa6}, {\xe2\x80\xa6}, {\xe2\x80\xa6}, \xe2\x80\xa6 ] //here   \n_view: Object { def: {\xe2\x80\xa6}, parent: {\xe2\x80\xa6}, state: 1036, \xe2\x80\xa6 }\n
Run Code Online (Sandbox Code Playgroud)\n

__embeddedViews动态生成的视图将堆叠在对象下的位置

\n

稍后为了决定删除哪些视图,此 stackblitz 的创建者只需获取组件并创建一个ViewContainerRef.indexOf(component)来获取存储组件的索引,并验证动态生成的组件是否存在于该数组中。然后他/她只需删除调用的视图this.ViewContainerRef.remove(index);

\n

有趣的是,在我的实现中,当我登录时,ViewContainerRef我得到这个对象作为响应:

\n
\xe2\x80\x8b_hostTNode: Object { type: 0, index: 23, injectorIndex: 34, \xe2\x80\xa6 }\n_hostView: Array(94) [ ..., {\xe2\x80\xa6}, 147, \xe2\x80\xa6 ]\n_lContainer: Array(12) [ <!-- \n
Run Code Online (Sandbox Code Playgroud)\n

芯片已按预期成功动态添加,但没有 _embeddedViews,因此我无法动态删除它们,因为ViewContainerRef.indexOf(chip)总是返回 -1 作为“不,我这里没有“芯片””\n请有人启发我并显示我在这里做错了什么?

\n

yur*_*zui 5

您之所以会出现这种不一致,是因为您以错误的方式使用 ViewContainerRef API。

这是indexOf方法的签名:

abstract indexOf(viewRef: ViewRef): number;
Run Code Online (Sandbox Code Playgroud)

这个签名在 Angular 更新期间从未改变。

您所指的 stackblitz 使用 Angular 6 版本,该版本在后台利用 ViewEngine,但在您的代码中,您使用的是 Angular 9 及更高版本,其中 Ivy 编译器发挥作用。

在 stackblitz 中你有:

this.VCR.indexOf(componentRef as any);
Run Code Online (Sandbox Code Playgroud)

这意味着您传递的是 ComponentRef 实例而不是 ViewRef 实例。它的工作是偶然的,因为indexOf方法看起来像:

ViewContainerRef_.prototype.indexOf = function (viewRef) {
  return this._embeddedViews.indexOf(viewRef._view);
};
Run Code Online (Sandbox Code Playgroud)

ComponentRef._view === ViewRef._viewViewEngine

您应该传递ViewRef实例:

this.VCR.indexOf(componentRef.hostView)
Run Code Online (Sandbox Code Playgroud)

叉式堆栈闪电战

该演示适用于 Ivy(您的具体情况),但它也适用于 ViewEngine。