问题 嵌套Angular2异步管如何解析?


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

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

在我的模板中,我只是在封闭的上面返回的observable上使用异步管道 <p> 标记以控制何时显示,然后尝试显示返回的数组长度 <p> 标签:

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

查看Plunker。

所以当你加载它时,会显示“等待列表”,2秒后我们会得到“我们有列表!” part,正如预期的那样,但内部异步管道需要另外2秒才能解析并显示已解析的数组长度。

如何在与Observable返回其值相关的其他所有内容的同时显示长度?或者这只是异步管道的一个很好的用例,我应该这样做 subscribe() 而在我的组件中呢?


6586
2018-03-03 02:19


起源



答案:


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

检查 NgIf 指令源代码。

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

this._viewContainer.createEmbeddedView(this._templateRef);

文件 ViewContainerRef#createEmbeddedView

基于templateRef实例化嵌入式视图,并将其插入到指定索引处的此容器中。

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

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

this._viewContainer.clear();

文件 ViewContainerRef#清晰

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

那么,既然我们知道NgIf做了什么,为什么你会看到这种行为?很简单,我会逐步解释

  1. <p *ngIf="!(lists | async)">Waiting for lists...</p> : 在此刻 lists 结果尚未到达,因此执行此操作。

  2. <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 你的代码工作。

我希望这有助于澄清一点。


11
2018-03-03 03:50



谢谢 - 有道理。运用 delay() 在我的观察中让我学习更多关于如何 *ngIf 工作:) - chucknelson
也许有必要提到源可观察的事实并非如此 共享 无论如何也起着重要的作用。在原始场景中 lists 可观察的是两次订阅(一次为 ngIf然后是 length),并在每次订阅时,流重新开始,包括延迟。如果 lists 如果共享,重放或变热,第二个订阅会立即找到最终的数组值,而不会有新的延迟。 - superjos


答案:


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

检查 NgIf 指令源代码。

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

this._viewContainer.createEmbeddedView(this._templateRef);

文件 ViewContainerRef#createEmbeddedView

基于templateRef实例化嵌入式视图,并将其插入到指定索引处的此容器中。

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

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

this._viewContainer.clear();

文件 ViewContainerRef#清晰

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

那么,既然我们知道NgIf做了什么,为什么你会看到这种行为?很简单,我会逐步解释

  1. <p *ngIf="!(lists | async)">Waiting for lists...</p> : 在此刻 lists 结果尚未到达,因此执行此操作。

  2. <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 你的代码工作。

我希望这有助于澄清一点。


11
2018-03-03 03:50



谢谢 - 有道理。运用 delay() 在我的观察中让我学习更多关于如何 *ngIf 工作:) - chucknelson
也许有必要提到源可观察的事实并非如此 共享 无论如何也起着重要的作用。在原始场景中 lists 可观察的是两次订阅(一次为 ngIf然后是 length),并在每次订阅时,流重新开始,包括延迟。如果 lists 如果共享,重放或变热,第二个订阅会立即找到最终的数组值,而不会有新的延迟。 - superjos


我有类似的问题,但有2个不同的观察。为了使它工作,我取代了 *ngIf="list | async" 至 [hidden]="!(list | async)"。这样可以保留DOM中的元素并更新数据。


0
2018-04-13 10:59