Angular:如何使用异步管道轻松地从 Observable 中提取假值?
目录
从模板中解包可观察对象
如何从可观察对象中解包假值?
结论
发现拼写错误?
跟我来
AWS 安全直播!
无论你使用 Angular 多年,还是昨天才开始接触它,你很可能都听说过ngIf指令。它允许你根据条件显示(创建或删除)DOM 元素。
虽然听起来很简单,但它有一个(原生)功能,ngIf似乎很多人都不知道。
目录
从模板中解包可观察对象
ngIf由于 Angular 与 RxJS 配合得非常好,因此当您有一个可观察对象时,可以使用async管道和以下语法来利用该指令as:
<div *ngIf="user$ | async as user">
{{ user.name }}
</div>
但是,如果想使用async管道从可观察对象中提取一个值为假值(falsy)的值,会发生什么情况呢?
例如,布尔值(值为真false,0数字为空)、空字符串、非null空undefined值等等。
ngIf由于条件被判定为假,因此该值不会显示。
这里存在一个长期存在的问题:https://github.com/angular/angular/issues/15280
如何从可观察对象中解包假值?
上述问题的主要提议是添加一个ngLet指令,该指令具有与现有指令相同的功能ngIf,但即使值为假,也始终显示模板。
这项ngLet指令能否成为解决这种情况的灵丹妙药?如果是,那么在它生效之前,我们该如何应对?
将该值包装成一个对象
使用运算符将可观察对象中的值包装成一个对象map。
例子:
const wrappedValue$ = falsyValue$.pipe(map(value => ({ value })));
如果我们能添加一个合适的类型定义和一个自定义的 rxjs 操作符,效果会更好。这样可以减少样板代码和重复代码,提高代码可读性。不错!
但是,由于显示问题而修改数据流,感觉我们可以/应该做得更好。而我们只需使用……Angular 就能做到!
直接使用 ngIf 就行了!
Angular 编译器允许你直接从模板中进行这种包装:
<div *ngIf="{ falsyValue: falsyValue$ | async } as data">
{{ data.falsyValue}}
</div>
这项功能似乎并不为人熟知,但它在很多方面都非常有用:
-
在上面的例子中,
data对象始终被定义,因此无论对象中包含什么内容,ngIf条件始终会被评估为真true。这可以替代ngLet指令。 -
我们可以通过一次订阅多个属性来进一步扩展功能,无需嵌套
div或ng-container使用 !
前:
<ng-container *ngIf="wrappedValue1$ | async as wrappedValue1">
<ng-container *ngIf="wrappedValue2$ | async as wrappedValue2">
<ng-container *ngIf="wrappedValue3$ | async as wrappedValue3">
{{ wrappedValue1 }} {{ wrappedValue2 }} {{ wrappedValue3 }}
</ng-container>
</ng-container>
</ng-container>
后:
<div
*ngIf="{
value1: value1$ | async,
value2: value2$ | async,
value3: value3$ | async
} as data"
>
{{ data.value1 }} {{ data.value2 }} {{ data.value3 }}
</div>
是不是干净多了?
结论
我认为,使用ngLet指令可以更清晰地阐明我们想要实现的目标,更重要的是,当我们只有一个可观察对象需要管理时,可以执行以下操作而不是将其包装成对象,这可能会很有用:
<div *ngLet="value$ | async as value">
{{ value }}
</div>
但就目前而言,这个变通方法很简单,不应该阻止你在转换模板端而不是在你的 TS 代码中进行转换。
祝您编程愉快!
发现拼写错误?
如果您发现这篇博文中有拼写错误、句子需要改进或其他任何需要更新的内容,您可以通过 Git 仓库访问并提交 pull request。请不要发表评论,直接访问https://github.com/maxime1992/my-dev.to并提交包含您更改的新 pull request。如果您想了解我如何通过 Git 和 CI 管理我的 dev.to 博文,请点击此处阅读更多内容。





