微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一旦设置了 2 个输入,然后在 Angular 中的任何一个值发生变化时触发一个函数

如何解决一旦设置了 2 个输入,然后在 Angular 中的任何一个值发生变化时触发一个函数

我有一个带有 2 个输入(或 mor)的组件,我想:

  1. 第一次触发方法 X,当两个值都设置并存在时
  2. 每次触发一个方法 X,如果两个值中的一个发生变化
<some-cmp [itemid]="activeItemId$ | async" [userId]="activeUserId$ | async"></some-cmp>

这两个值都可以随时更改,因此我认为使用 rxjs 构建流可以让我控制一切。我目前的解决方案似乎有点老套,难以测试。我将 2 BehavIoUrSubjectscombineLatestdebounceTime 一起使用。

@input() set itemId (id){this.itemId$.next(id)};
@input() set userId (id){this.userId$.next(id)};

itemId$ = new BehavIoUrSubject$(null);
userId$ = new BehavIoUrSubbject$(null);

ngOnInt(){
    combineLatest([
        this.itemId$.pipe(filter(item=>item!===null)),this.userId$.pipe(filter(item=>item!===null))
    ]).pipe(
        debounceTime(10),switchMap(...)
    ).subscribe(...)
}

所以我的问题是

  1. 是否有更优雅的方式来实现这种行为?
  2. 有没有办法避免使测试变得困难的 debounceTime

如果两个值确实同时到达并且我不希望 debounceTime 触发该方法两次,则使用 combineLatest

解决方法

Angular 提供了 ngOnChanges 钩子,可以在这种情况下使用。只要组件的任何输入发生变化,它就会触发 ngOnChanges 方法。

以下是如何实现这一目标的示例:

export class SomeComponent implements OnChanges {
    @Input() itemId: any;
  
    @Input() userId: any;
  
    ngOnChanges(changes: SimpleChanges) {
      const change = changes.itemId || changes.userId;
  
      if (change && change.currentValue !== change.previousValue) {
        this.doSomething();
      }
    }
  
    private doSomething() {
      // Your logic goes here
    }
  }

您的 HTML 现在看起来很干净,您也可以去掉 async

<some-cmp [itemid]="itemId" [userId]="userId"></some-cmp>
,

您使用 combineLatest 是正确的,它只会在每个源发出一次后第一次发出,然后在任何源发出时都会发出。

有没有办法避免 debounceTime。 [It] 用于两个值同时到达并且我不希望 combineLatest 触发该方法两次的情况。

由于 debounceTime 的初始行为,可能不需要 combineLatest;它不会第一次发射,直到所有源发射。但是,如果您通常会在短时间内收到来自两个来源的后续排放,则使用 debounceTime 可能是适当的优化。

有没有更优雅的方式来实现这种行为?

我认为你的代码很好。但是,可能没有必要使用 BehaviorSubject,因为您并没有真正使用默认值。您可以使用普通的 SubjectReplaySubject(1)

您可以将 combineLatest 的结果分配给另一个变量并在 ngOnInit 内订阅该结果或使用模板中的 async 管道:

@Input() set itemId (id){ this.itemId$.next(id) };
@Input() set userId (id){ this.userId$.next(id) };

itemId$ = new Subject<string>();
userId$ = new Subject<string>();

data$ = combineLatest([
    this.itemId$.pipe(filter(i => !!i)),this.userId$.pipe(filter(i => !!i))
]).pipe(
    debounceTime(10),switchMap(...)
);

ngOnInit() {
  this.data$.subscribe(...);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。