【问题标题】:In Angular2 I need to show and hide child components from within a parent component在 Angular2 中,我需要在父组件中显示和隐藏子组件
【发布时间】:2018-03-29 13:09:45
【问题描述】:

在 Angular2 中如何最好地显示和隐藏子组件?

我有一个父组件三个子组件

默认情况下onInit需要隐藏所有子组件。 而childComponentA需要在父组件中显示一个按钮的onclick。

流程:

我在 childComponentA 中有一个按钮需要在点击时显示 childComponentB,而 childComponentB 组件有一个按钮需要显示 childComponentC。就像一个展示和隐藏的流程。

如何做到最好?

可能的解决方案?

我正在考虑创建一个服务,所有子组件都订阅以显示和隐藏。但不确定它是否是最佳解决方案。

父组件 HTML:

<section>
   <button (click)="showChildComponentA()"></button>

   <childComponentA></childComponentA>
   <childComponentB></childComponentB>
   <childComponentC></childComponentC>
</section>

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    如果你想保持你的代码干净和可维护,并且不到处都有布尔标志,最好使用一个服务(可能称为ToggleService)来处理切换和检查是否有东西应该显示出来。

    例如,这是一个简单的ToggleService,它使您能够创建新项目、删除项目以及使用显示/隐藏方法切换项目的可见性(请记住,以下内容没有经过测试,我真的只是为这个问题即时写了这一切——但这一切似乎都是合乎逻辑的,应该可行):

    @Injectable()
    export class ToggleService {
        toggleMap: {[uniqueKey: string]: any} = {};
    
        create(key: string) {
            this.toggleMap[key] = null;
        }
    
        remove(key: string) {
            delete this.toggleMap[key];
        }
    
        isShown(key: string): boolean {
            return this.toggleMap[key];
        }
    
        show(key: string) {
            this.toggleMap[key] = true;
        }
    
        hide(key: string) {
            this.toggleMap[key] = false;
        }
    }
    

    现在在您的组件中,您可以利用该服务:

    @Component({...})
    export class MyComponent implements OnInit, OnDestroy {
        constructor(public toggleService: ToggleService) {}
    
        ngOnInit() {
            this.toggleService.create('componentOne');
            this.toggleService.create('componentTwo');
            this.toggleService.create('componentThree');
        }
    
        // Clean up when parent component is destroyed to save memory
        ngOnDestroy() {
            this.toggleService.remove('componentOne');
            this.toggleService.remove('componentTwo');
            this.toggleService.remove('componentThree');
        }
    }
    

    在模板中:

    <button (click)="toggleService.show('componentOne')">Show component 1</button>
    <button (click)="toggleService.show('componentTwo')">Show component 2</button>
    <button (click)="toggleService.show('componentThree')">Show component 3</button>
    
    <componentOne *ngIf="toggleService.isShown('componentOne')"></componentOne>
    <componentTwo *ngIf="toggleService.isShown('componentTwo')"></componentTwo>
    <componentThree *ngIf="toggleService.isShown('componentThree')"></componentThree>
    

    请记住,单击其中一个按钮不会隐藏另一个按钮。为此,您可能需要创建一个 toggle 方法,该方法将遍历服务中的整个 toggleMap 并使所有内容为 false,然后仅将一件事设置为 true。

    我会把最后一点留给你做练习;)

    【讨论】:

    • 嗨 Lansana,我在想一个可观察的主题在具有像这样的对象的服务中会更好 {childAVIsible: true, etc }
    • ToggleService 中的可观察主题在这里也同样有效。
    【解决方案2】:

    我会选择基于组件的设计。在我看来,事件驱动设计并不酷,因为很难追踪哪个组件与哪个事件发布者交互。

    Stackblitz example

    <button (click)="changeFlag(CompFlags.Comp1)">Show comp1 </button>
    <br>
    <comp1 *ngIf="checkState(CompFlags.Comp1)"  (clicked)="changeFlag(CompFlags.Comp2)"></comp1>
    <br>
    <comp2  *ngIf="checkState(CompFlags.Comp2)" (clicked)="changeFlag(CompFlags.Comp3)"></comp2>
    <br>
    <comp3  *ngIf="checkState(CompFlags.Comp3)"></comp3>
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html'
    }) 
    export class AppComponent  {
      CompFlags = CompFlags;
      state = CompFlags.None;
    
      changeFlag(flag:CompFlags){
        (this.state & flag) ? this.state &= ~flag : this.state |= flag;
      }
    
      checkState(flag:CompFlags){
        return !!(this.state & flag);
      }
    }
    
    export enum CompFlags{
      None = 0,
      Comp1 = 1 << 0,
      Comp2 = 1 << 1,
      Comp3 = 1 << 2
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 2015-07-06
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多