【问题标题】:Angular 6 - Multiple child components should be of same instanceAngular 6 - 多个子组件应该是同一个实例
【发布时间】:2018-12-04 20:21:28
【问题描述】:

我简化了我的问题:

<div *ngIf="layout1" class="layout1">
  <div class="sidebar-layout1">
     some items
  </div>
  <child-component [something]="sth"></child-component>
</div>
<div *ngIf="!layout1" class="layout2">
  <child-component [something]="sth">
    <p>some content...</p>
  </child-component>
</div>

我有一个父组件,它具有正常布局(layout1)和全屏布局(layout2)的可能性(在全屏模式下,子组件应该全屏)。问题是, 当我使用 *ngIf 更改布局时,子组件被销毁并生成一个新组件。我想拥有相同的实例,不要丢失子组件的重要信息,避免一些 a​​pi 调用。

有什么方法可以实现子组件不会被销毁,或者有没有比 ngIf 更好的方法?

对于父组件中的不同布局,我只需要一个子组件实例。

【问题讨论】:

  • 但使用 [hidden] 仍然占用空间。相反,在 ngStyle 上设置 display:none。这只是我的假设。试一试。我需要知道“!layout1”是任何标志或布尔值吗?
  • layout1 只是一个布尔标志,我在按钮单击事件上更新
  • 好的。尝试这个。再添加一个标志,例如 if(this.paraentLayout == false){ dont made change in child} 即 *ngIf == ' parentLayout == false ? classA : ClassB'
  • 我将只使用一个孩子和 ngClass 跨度>

标签: angular scope components directive


【解决方案1】:

您可能已经注意到,如果您使用*ngIf 隐藏元素,则会创建一个新组件。这是我们将努力关注并尽量避免创建新组件的内容。

为此,我们可以使用“切换器布局”并将子组件作为内容传递

<app-layout-switcher [layout1]="layout1">
  <ng-container>
    <child-component
      *ngIf="sth$ | async as sth; else loading"
      [something]="sth"
    >
      <p>some content...</p>
    </child-component>
    <ng-template #loading>
      <h1>Loading...</h1>
    </ng-template>
  </ng-container>
</app-layout-switcher>

我添加了一个模拟 http 调用来显示加载。

在我们的app-layout-switcher 组件中,我们可以根据需要在布局之间切换。我们会将child-component 传递到模板中,以便能够在布局中重用它

<div *ngIf="layout1">
  <app-layout-1>
    <ng-template [ngTemplateOutlet]="childComponent"></ng-template>
  </app-layout-1>
</div>

<div *ngIf="!layout1">
  <app-layout-2>
    <ng-template [ngTemplateOutlet]="childComponent"></ng-template>
  </app-layout-2>
</div>

<ng-template #childComponent>
  <ng-content></ng-content>
</ng-template>

现在我们可以在布局中使用模板

<header>
  <h1>Layout 1</h1>
</header>
<main>
  Contents in Layout 1
  <div>
    <ng-content></ng-content>
  </div>
</main>

<footer>Layout 1 Footer</footer>

我们现在只使用该组件的一个实例。为了确认这一点,我在演示中添加了一个文本字段。你会注意到切换布局时数据是持久化的

See this Demo

【讨论】:

  • 嗨@Owen Kelvin。谢谢你的回答。它适用于一个组件。但是对于在&lt;ng-content&gt; 标签中使用select 的多个子组件,它是如何工作的呢?似乎选择标签在布局切换器中丢失了。
【解决方案2】:

使用 [hidden] 属性与反向逻辑相反,它会防止元素被破坏。

<div [hidden]="!layout1" class="layout1">
...
</div>
<div [hidden]="layout1" class="layout2">
...
</div>

我 hidden 只是通过更改显示样式来隐藏/显示带有 css 的 DOM 元素

【讨论】:

  • 但使用 [hidden] 仍然占用空间。相反,在 ngStyle 上设置 display:none。这只是我的假设。试一试
  • 但我仍然有两个不同的子组件实例。我需要一种方法来只拥有一个子组件实例以不丢失它的信息
【解决方案3】:

您可以通过几个步骤实现:

  1. 使用此命令创建服务:
ng generate service data-passing
  1. 在该服务中定义两个变量来保存每个组件的数据:
import {Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DataPassingService {
  public firstComponentData;
  public secondComponentData;

  constructor() { }

}
  1. 在您的组件中使用服务:
import {DataPassingService} from '...';

...
constructor(public dataPassingService: DataPassingService) {
}
  1. 将每个组件数据存储在相对变量中:
setDate(first, second) {
  this.dataPassingService.firstComponentData = first;
  this.dataPassingService.secondComponentData = second;
}
  1. 像以前一样使用*ngIf 来控制组件的可见性:
<div *ngIf="layout1" class="layout1">
  <div class="sidebar-layout1">
     some items
  </div>
  <child-component [something]="dataPassingService.firstComponentData"></child-component>
</div>
<div *ngIf="!layout1" class="layout2">
  <child-component [something]="dataPassingService.secondComponentData">
    <p>some content...</p>
  </child-component>
</div>

【讨论】:

    【解决方案4】:

    当您想在两种不同的布局中显示相同/不同的细节时:

    • 为状态管理实现秋田商店 https://datorama.github.io/akita/docs/store
    • 从父组件本身的服务中获取所需的所有数据。
    • 将接收到的数据从服务更新到存储中。
    • 通过在两种布局中使用查询来订阅商店。
    • 更新用户在商店中所做的最新更新。

    【讨论】:

      猜你喜欢
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 2019-07-07
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      相关资源
      最近更新 更多