如何给c:foreach 出来的div如何显示隐藏_最干净的方法之一!如何在Angular应用程序中管理RxJS订阅...

全文共2792字,预计学习时长13分钟

19e5523c19d84df0815bb1ac270eff66.png

图源:unsplash

在一个Angular组件内处理多个可观察对象的RxJS,需要在某个地方订阅它们,更重要的是,当不再需要时可以取消订阅。

有成千上万的文章告诉我们,经常退订是多么重要。内存泄漏,性能下降,疯狂的副作用——这些都可以由一个未订阅的可观察对象触发。

那么该如何操作呢?关于如何在Angular应用程序中管理RxJS订阅的教程,网上已经有很多了。但笔者的方法一定是最干净的方法之一。不相信?那就往下看吧~

2f500af8edaf88c3997bce07a4f81060.png

有成千上万的文章在解释如何正确退订,如何避免使用管理订阅的代码以免组件代码过载。你可以使用RxJS操作符来帮忙,也可以使用ngOnDestroy钩子、Subject或组件基类。

80f1ed41e44fc736509a337dd1d7e6a7.png

图源:unsplash

办法是很多的,但按照这样做,不管怎么努力,都会让组件代码有点混乱。然后组件中应用程序逻辑就与添加的一些订阅管理代码搞混了,而订阅管理代码本来是防止可怕的内存泄漏的。可读性不太好。即使是非常简单的组件看起来也有点复杂和可怕……

不如来试试笔者的办法。

5cf2b0e20ce869eec638d29f7397741e.png

异步管道救援?

63272914cb7ac4059fb32c8b0d241afe.png

图源:unsplash

只想在组件创建时订阅一些可观察对象,然后在组件被销毁时取消所有订阅。为什么要为此编写一行代码?这似乎是最常见的情况。为什么要自己处理?框架不能帮忙吗?

是的,它可以:Angular的异步管道。

可以在组件模板中使用异步管道。将可观察对象传递给异步管道,然后订阅,返回值,最后当组件被破坏时取消订阅。至少乍一看,这就足够了。

假设有一个可观察对象lastComment$返回最后一个评论的对象。假设要在模板中打印注释内容。可以这样做:

Lastcomment

{{ (lastComment$ | async).body }}

现在看来一切都还不错。但如果还想添加评论主题呢

​x
<h1>Lastcomment</h1>
<h2>{{ (lastComment$ | async).subject }}</h2>
<div>{{ (lastComment$ | async).body }}</div>

emmm…不再那么酷了,订了两份而不是一份。每次使用异步管道都会创建一个单独的订阅(即便使用相同的可观察对象)。

想象一下,在可观察对象lastComment$下,隐藏了对API或一些复杂数据处理的HTTP请求。对于两个单独的订阅,需要执行两次而不是一次操作。听起来有点麻烦,那么该怎样做呢?

可以利用*ngIf指令来帮助自己。用div元素封装所有内容。添加*ngIf并在其中订阅lastcoment$。

...

每当发出一条评论,都会显示div内容。如果没有任何评论,整个div都将被隐藏。是不是很完美?

可以将异步管道结果保存在变量下,并在*ngIf显示的元素中使用这个变量。这样的操作你可能见过很多次:调用comment变量。

Last comment

{{ comment.subject}}

{{ comment.body}}

看起来已经搞定了,对吧?还没完!

现在想象一下组件模板有点大,评论数据显示在两个或多个位置,并用其他内容分隔。假设要打印评论作者的姓名,然后是一篇博客文章,然后是所有评论的详细信息,该怎么做?如下所示:

This was recently commented by {{comment.author }}!

Post

{{blogPost.subject }}

{{ blogPost.body}}

Last comment

{{comment.subject }}

{{ comment.body}}

rawlastcoment.js|GitHub

又是有多个订阅!继续封装di还有用吗?不会又起作用?看看:

This was recently commented by {{comment.author }}

Post

{{blogPost.subject }}

{{ blogPost.body}}

Last comment

{{comment.subject }}

{{ comment.body}}

rawlastcoment.js | GitHub

它不再有用了,至少不总是这样。

注意:如果根本没有lastComment,则异步管道返回null。然后,*ngIf指令隐藏整个div及其所有内容,以及保持可见的无关blogPost元素。

那么,在这种情况下,异步管道是否就失效了?你得被迫手动管理订阅?还是需要在模板中使用多个订阅?

不不不,只要知道怎么做,仍然可以使用异步管道!

417b91bc918cb61ac5cd745c60b5f8e7.png

像职业选手一样异步

只需要从可观察对象lastComment$创建一个新的可观察对象,并确保它总是返回一个真实的值。稍微转换一下可观察对象lastComment$,并将其称为componentContext$。

letcomponentContext$ = this.lastComment$.pipe(  map(lastComment => ({ lastComment})));

完成了!请注意,新的可观察对象总是返回一个真实的值(对象),即使lastcoment$发出null。如果为空,则返回值如下:{lastComment:null}。来看看它的表现吧:

This was recently commented by {{comment.author }}

Post

{{blogPost.subject }}

{{ blogPost.body}}

Last comment

{{comment.subject }}

{{ comment.body}}

rawcomponentContext.js | GitHub

一切正常。封装div始终可见,因为componentContext$发出的值总是真实的。显示或隐藏内部div取决于lastComment的值。检查相应的内部*ngIfs中的ctx.lastcoment属性并作出适当反应。

看看它看起来有多干净:有一个异步管道、一个订阅和一个完全工作的组件。

0bae4c451377943a91329b8f98300416.png

图源:unsplash

而且所有订阅现在都由异步管道本身控制,不必像Angular那样担心是否会及时取消订阅。

417b91bc918cb61ac5cd745c60b5f8e7.png

组件上下文可观察对象

在上面创建的可观察对象——组件上下文可观察对象,它是一个由组件使用的所有可观察对象组成的单一可观察对象。它发出组件上下文对象,其中包含组件需要正确呈现的所有数据。

为了确保上下文可观察对象每次都发出,一旦它的一个源可观察对象产生一个值,就可以使用CombineTest运算符创建它。

一般来说,可以这样创建:

@Component({...})                exportclassExampleComponent implements OnInit {                ngOnInit() {                  ...this.context$=combineLatest(this.blogPost$,this.lastComment$                  ).pipe(                    map(([blogPost, lastComment]) => {return { blogPost, lastComment };                    })                  );                  ...                }                }

rawExampleComponent.js | GitHub

一旦配置好,就可以像这样使用:

This was recently commented by {{comment.author }}

Post

{{blogPost.subject }}

{{ blogPost.body}}

rawcontext.js | GitHub

构建在组件中管理RxJS可观察对象的方式,可以总结为以下三条规则,在整个应用程序中都可应用:

1.不要直接在组件代码中订阅可观察对象。如果不需要,则不必管理它们的订阅。需要订阅组件中的可观察对象时,去使用异步管道。

2.创建组件上下文可观察对象,它由要在组件中使用的可观察对象组成。确保它总是发出真实的价值。

3.使用异步管道和*ngIf订阅组件模板开头的上下文可观察对象,并通过变量将发出的上下文对象传递给模板的其余部分。一旦组件被销毁,所有订阅都将被异步管道终止。

0dc2768c2be4494ba645f7bd7e50b5a6.png

图源:unsplash

这个最干净的解决方案,你学会了吗?

79220c42ed440a9761fe2bb2ad11d126.png

留言点赞关注

我们一起分享AI学习与发展的干货

如转载,请后台留言,遵守转载规范

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值