首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组件中的输入/服务数据组合

组件中的输入/服务数据组合
EN

Stack Overflow用户
提问于 2020-05-11 14:59:06
回答 2查看 141关注 0票数 1

我有一个角分量,它从@Input变量中获取数据,并使用它过滤来自服务的其他数据。(简化)结构如下所示:

代码语言:javascript
复制
<phones-component>
 <phone-details>
  <..>
  <phone-history-component [phoneNumber$]="phoneNumber$"></phone-history-component>
 <phone-details>
</phones-component>

PhoneDetailsComponent:

代码语言:javascript
复制
 changeLogs$: Observable<AuditLog[]>;

 constructor(
   private auditLogService: AuditLogService, //ngrx-data service
 ){

  ngOnInit(): void {
      this.changeLogs$ = combineLatest([this.phoneNumber$, this.auditLogService.entities$])
           .pipe(
                 map(pn => pn[1].filter(logs => logs.pkId === pn[0].id))); //filters the logs to show only log entries from the corresponding phonenumber
   }

这些路由配置如下:

代码语言:javascript
复制
{
  path: 'phones',
  component: PhonesComponent,
},
{
  path: 'phones/:id',
  component: PhoneDetailsComponent,
},

只要我从父容器‘输入’PhoneDetailsComponent,一切都能正常工作。当用户手动重新加载PhoneDetails视图时,changeLogs$数组是空的,除非我手动注入一个可观察到的未包装属性,如下所示:

代码语言:javascript
复制
  <phone-history-component [phoneNumberId]="(phoneNumber$ | async).id" [phoneNumber$]="phoneNumber$"></phone-history-component>

如果我像这样注射电话号码$

代码语言:javascript
复制
[phoneNumber]="(phoneNumber$ | async)"

它不起作用。(我在组件中不使用这些额外的输入)

现在我知道还有其他方法来实现这个功能,但是我只想知道为什么代码是这样的呢?

我觉得我对基本的rxjs管道缺乏一些基本的理解。So..what到底在这里发生了什么?

任何帮助都是非常感谢的。

UPDATE BizzyBob是对的。当直接重新加载组件时,当首次执行phoneNumber$函数时,可观察到的filter没有任何值。我用快速检查来修正这个问题:

代码语言:javascript
复制
  map(pn => {
        return !!pn[0] ? pn[1].filter(logs => logs.pkId === pn[0].id) : null;
      }));

现在.。这是推荐的方法,还是有更好的方法?

EN

回答 2

Stack Overflow用户

发布于 2020-05-13 13:55:21

要创建正确的rxjs样条,可以使用startWith运算符和switchMap。那么您的代码将如下所示:

代码语言:javascript
复制
ngOnInit(): void {
  this.changeLogs$ = this.phoneNumber$
                          .pipe(
                             startWith({}),
                             switchMap(item => this.filterData(item))
                              );
 }

filterData(value = {}): Observable<any>{
 return this.auditLogService.entities$
            .pipe(
                map(data => data.filter(logs => logs.pkId === value.id))
                );
 }
票数 2
EN

Stack Overflow用户

发布于 2020-05-13 12:44:17

phoneNumber$是如何定义的?这可能是formControl.valueChanges可以观察到的吗?这不会调用初始值,因此可以使用rxjs startWith()操作符。如果你不能使用它(因为一些奇怪的原因),那么BehaviorSubject是下一个选择。

我用代码片段复制了您的问题,并提供了2种推荐的解决方案。瞧一瞧!

代码语言:javascript
复制
let changeLogs$ = null;
let phoneNumber$ = null;
let auditLogService = {
  entities$: rxjs.of([{pkId: 1}])
}

function ngOnInit() {
      changeLogs$ = rxjs.combineLatest([phoneNumber$, auditLogService.entities$])
           .pipe(
                 rxjs.operators.map(pn => pn[1].filter(logs => logs.pkId === pn[0].id)))
   }
   
console.log('empty observable');
phoneNumber$ = rxjs.of();
ngOnInit();
let subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();

console.log('observable with data');
phoneNumber$ = rxjs.of({id: 1})
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();

console.log('empty observable with startWith');
phoneNumber$ = rxjs.of().pipe(rxjs.operators.startWith({id: 1}));
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));
subscribtion.unsubscribe();

console.log('behaviorsubject with data');
phoneNumber$ = new rxjs.BehaviorSubject({id: 1})
ngOnInit();
subscribtion = changeLogs$.subscribe(data => console.log(data));
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61732780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档