【问题标题】:How do Nested Angular2 Async Pipes Resolve?嵌套的 Angular2 异步管道如何解决?
【发布时间】:2016-03-03 02:19:16
【问题描述】:

我对嵌套异步管道如何以及何时在 angular2 模板中解析感到有些困惑,而且文档现在不是很好,所以我希望 SO 上的人可以提供帮助。

我有一个非常简单的 Rxjs Observable 从服务返回,通过 Observable.of(myArray).delay(2000) - 延迟是为了帮助显示时间发生了什么。

在我的模板中,我只是在封闭的<p> 标记中使用上面返回的可观察对象上的异步管道来控制它何时显示,然后尝试在该<p> 标记内显示返回的数组长度:

<p *ngIf="!(lists | async)">Waiting for lists...</p>
<p *ngIf="lists | async">We have lists! How many? => {{(lists | async)?.length}}</p>

View the Plunker.

因此,当您加载此内容时,会显示“等待列表”,2 秒后我们会看到“我们有列表!”部分,正如预期的那样,但内部异步管道需要另外 2 秒才能解析并显示解析的数组长度。

如何让长度与依赖于 Observable 返回其值的所有其他内容同时显示?或者这对于异步管道来说不是一个很好的用例,我应该只在我的组件中使用subscribe()

【问题讨论】:

    标签: angular


    【解决方案1】:

    异步管道很好。这个主题还涉及另一件事。

    查看NgIf指令源代码。

    当条件为真时,它会将视图嵌入到视图容器中。

    this._viewContainer.createEmbeddedView(this._templateRef);
    

    ViewContainerRef#createEmbeddedView的文档

    根据 templateRef 实例化一个 Embedded View 并将其插入到此容器中的指定索引处。

    基本上,它获取 NgIf 中的任何内容,将其实例化并将其放入 DOM。

    当条件为假时,它会从 DOM 中删除所有内容并清除其中的所有视图

    this._viewContainer.clear();
    

    ViewContainerRef#clear 的文档

    销毁此容器中的所有视图。

    那么,既然我们知道了 NgIf 的作用,那么您为什么会看到这种行为呢?很简单,我分步​​讲解

    1. &lt;p *ngIf="!(lists | async)"&gt;Waiting for lists...&lt;/p&gt; :此时lists 结果还没有到达,所以执行了。

    2. &lt;p *ngIf="lists | async" :此 ngIf 将在两秒内执行(您为其设置的延迟时间)。一旦值到达,NgIf 指令将实例化它内部的内容并将其放入 DOM。

    3. (lists | async)?.length :这个异步管道一旦被实例化就会执行,比上面晚两秒。

    所以你的时间线应该是这样的(真的很抱歉我糟糕的时间线设计)

    *ngIf="lists | async" 
    ----(2 seconds)-----> 
    
                         (lists | async)?.length 
                         ------(2 seconds)----->   
                                                  print value
    

    这就是您看到这种差异的原因。 *ngIf 未与 ?.length 并行运行。

    如果您想立即查看,则必须删除 delay 运算符,或手动订阅并自行设置值,如下所示

    // Template
    <p *ngIf="lists">We have lists! How many? => {{lists.length}} some value</p>
    
    // Observable
    this._listService.getLists(2000).subscribe(res => this.lists = res);
    

    这当然会影响您的其他异步管道。看到这个plnkr 你的代码工作。

    我希望这会有所帮助并澄清一点。

    【讨论】:

    • 谢谢 - 有道理。在我的 observable 上使用 delay() 让我更多地了解*ngIf 的工作原理:)
    • 也许值得一提的是,源 observable 不以任何方式共享​​>这一事实也起着重要作用。在原始场景中,lists observable 被订阅了两次(一次用于ngIf,然后用于length),并且在每次订阅时,流都会重新开始,包括延迟。如果lists 被共享、重放或变热,第二个订阅将立即找到最终的数组值,而不会出现新的延迟。
    【解决方案2】:

    我有类似的问题,但有 2 个不同的 observables。为了使它工作,我将*ngIf="list | async" 替换为[hidden]="!(list | async)"。这会将元素保留在 DOM 中并更新数据。

    【讨论】:

      猜你喜欢
      • 2016-06-24
      • 2021-01-24
      • 1970-01-01
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      • 2017-02-14
      • 2016-11-08
      • 1970-01-01
      相关资源
      最近更新 更多