结合* ngIf

时间:2018-08-02 14:33:33

标签: angular

Component的子项并非总是被创建时,我正在努力寻找一种管理*ngIf的子项的好方法。

组件RootComponent的HTML结构:

<div id="root-div" *ngIf="dto">
    <div id="nested-div-1" *ngIf="something">
        <my-nested-component>
        </my-nested-component>
    </div>
    <div id="nested-div-2" *ngIf="somethingElse">
        <div #anotherChild>
        </div>
    </div>
    <button (onClick)="setSomethingElse()">Button</button>
</div>

问题:

  • RootComponent已呈现。
  • REST中调用
  • ngAfterViewInit以获得dto,直接设置something布尔值

    @ViewChild() myNestedComponent : MyNestedComponent;
    
    ngAfterViewInit() {
        restService.get().then((result) => {
            this.dto = result;
            this.something = true;
        }
    }
    
  • Angular现在将渲染root-divnested-div-1my-nested-component

  • 执行以下操作时,您将获得undefined异常:

    @ViewChild() myNestedComponent : MyNestedComponent;
    
    ngAfterViewInit() {
        restService.get().then((result) => {
            this.dto = result;
            this.something = true;
    
            this.myNestedComponent.theMethod();
        }
    }
    
  • 这很合理,因为Angular尚未更新视图,因此myNestedComponent未定义

错误/棘手的解决方案

  1. 使用ChangeDetectorRef.detectChanges()强制Angular更新视图
  2. this.myNestedComponent.theMethod()包裹在setTimeout中,这会延迟该行的执行,直到Angular完成周期为止。

更好的解决方案

  1. my-nested-component一个@Output事件,以便my-nested-component可以在完成初始化后在RootComponent中执行一个方法(例如,在{{1}中) ngAfterViewInit中的}

    my-nested-component

    这种方法的问题在于,当RootComponent想要对myNestedComponent进行操作时,需要检查<my-nested-component (afterInit)="nestedComponentInitialized()"></my-nested-component> nestedComponentInitialized() { this.myNestedComponentIsInitalized = true; this.myNestedComponent.theMethod(); // Works now! }

  2. 使用this.myNestedComponentIsInitalized的setter时可以避免这种初始化方法。但每个@ViewChild()

    仍需要一些代码
    @ViewChild
  3. myNestedComponent: MyNestedComponent; @ViewChild() set myNestedComponentSetter(myNestedComponent: MyNestedComponent) { this.myNestedComponentIsInitalized = true; this.myNestedComponent = myNestedComponent; } 更改为@ViewChild,以便可以侦听该列表的更改,这意味着该组件是初始化的。

    @ViewChildren

    这种方法的问题在于,您只能侦听列表中的更改,当您已经知道@ViewChildren() myNestedComponents : QueryList<MyNestedComponent>; ngAfterViewInit() { restService.get().then((result) => { this.dto = result; this.something = true; this.myNestedComponents.changes.subscribe(() => { this.myNestedComponentIsInitalized = true; this.myNestedComponents[0].theMethod(); } } } 中只有一个MyNestedComponent时,这很奇怪。这样做的好处是您可以订阅初始化事件。

例如,当您有4个不同的嵌套组件时,这三个“更好的解决方案”将成为噩梦。因为这意味着RootComponent需要4个初始化方法(或4个RootCompoment),并且需要4个布尔值来嵌套组件的状态。管理所有这些变得非常复杂。

  1. 不要使用QueryList,而要使用*ngIf,以便一切都永远存在。这听起来不错,但这意味着所有内容始终都会渲染,并且有时您仍然需要检查是否存在某些内容。因为这是不可能的(因为[hidden]可能引发异常,因为dto.name尚未通过dto调用进行初始化):

    REST

优雅的解决方案?

我正在寻找一种解决方案,可以管理由于<div id="root-div" [hidden]="dto"> <div id="nested-div-1" [hidden]="something"> <my-nested-component> </my-nested-component> </div> <div id="nested-div-2" [hidden]="!somethingElse"> <div #anotherChild> <span>{{dto.name}}</span> <!-- EXCEPTION, dto is not there yet! --> </div> </div> <button (onClick)="setSomethingElse()">Button</button> </div> 条件而并非总是初始化的组件的状态。

我想做类似的事情:

  • 等待REST请求完成并初始化*ngIfmy-nested-component
  • anotherChild初始化(因此anotherChildmy-nested-component为true,并且anotherChilddto时将somethingElse的组件引用传递给my-nested-component也在那里(所以something也是如此)

TLDR

当嵌套的Component由于* ngIf而并不总是存在时,管理它们的最佳模式或方法是什么?

1 个答案:

答案 0 :(得分:2)

我认为最好的解决方案是针对容器/组件方法设计角度项目。

这意味着您具有处理数据的容器(父级)和仅基于输入值呈现的子级。所有导致数据更新的操作都应通过子级向其父级的输出发出,父级更新数据,并通过输入将更新后的数据再次传递给子级。

因此您的数据流将始终像这样:service-> container-> component。

该概念主要来自于磁通/ redux模式和反应,但在角度方面也提供了很多优势。好处是:

  • 很少使用viewchild(总是有未定义的问题)
  • 更好地使用ChangeDetection策略(孩子们经常可以使用ChangeDetection.OnPush)
  • 它迫使人们认真考虑应用程序结构
  • 它使代码更具可读性,并且没有过载的组件

对于Rest请求,也可以将异步管道与ngIf结合使用,当所有数据可用时,将渲染您的孩子。在这里看看:https://toddmotto.com/angular-ngif-async-pipe

可以在以下位置找到有关容器/组件结构的良好指南:https://www.thegreatcodeadventure.com/the-react-plus-redux-container-pattern/

还有此处:https://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/

我知道这是一个巨大的话题,我无法在一篇文章中解释其所有复杂性,但是也许它会给您一些启发。

相关问题