我有一个父组件(CategoryComponent)、一个子组件(videoListComponent)和一个ApiService。

我的大部分工作都很好,即每个组件都可以访问jsonapi,并通过可观测获取相关数据。

目前,视频列表组件只获取所有视频,我想将其过滤为特定类别中的视频,我通过@Input()将categoryId传递给孩子来实现这一点。

类别组件.html

<video-list *ngIf="category" [categoryId]="category.id"></video-list>

这是有效的,当父CategoryComponent类别发生更改时,categoryId值将通过@Input()传递,但我需要在VideoListComponent中检测到这一点,并通过APIService(使用新的categoryId)重新请求视频数组。

在AngularJS中,我会对变量进行$watch。处理此问题的最佳方法是什么?


当前回答

我只想补充一点,如果@Input值不是基元值,还有一个名为DoCheck的Lifecycle钩子很有用。

我有一个数组作为输入,所以当内容发生变化时,这不会触发OnChanges事件(因为Angular所做的检查是“简单”的,而且不深入,所以即使数组上的内容发生了变化,数组仍然是一个数组)。

然后,我实现了一些自定义检查代码,以决定是否要使用更改后的Array更新视图。

其他回答

您可以在facade服务中使用BehaviorSubject,然后在任何组件中订阅该主题,当事件发生时触发对其的数据调用.next()的更改。请确保在销毁生命周期挂钩中关闭这些订阅。

data-api.facade.ts

@Injectable({
  providedIn: 'root'
})
export class DataApiFacade {

currentTabIndex: BehaviorSubject<number> = new BehaviorSubject(0);

}

某些组件

constructor(private dataApiFacade: DataApiFacade){}

ngOnInit(): void {
  this.dataApiFacade.currentTabIndex
    .pipe(takeUntil(this.destroy$))
       .subscribe(value => {
          if (value) {
             this.currentTabIndex = value;
          }
    });
}

setTabView(event: MatTabChangeEvent) {
  this.dataApiFacade.currentTabIndex.next(event.index);
}

ngOnDestroy() {
  this.destroy$.next(true);
  this.destroy$.complete();
}

此解决方案使用代理类并提供以下优点:

允许消费者利用RXJS的力量比目前提出的其他解决方案更紧凑比使用ngOnChanges()更安全您可以通过这种方式观察任何类字段。

示例用法:

@Input()
num: number;
@Input()
str: number;
fields = observeFields(this); // <- call our utility function

constructor() {
  this.fields.str.subscribe(s => console.log(s));
}

实用程序功能:

import { BehaviorSubject, Observable, shareReplay } from 'rxjs';

const observeField = <T, K extends keyof T>(target: T, key: K) => {
  const subject = new BehaviorSubject<T[K]>(target[key]);
  Object.defineProperty(target, key, {
    get: () => subject.getValue() as T[K],
    set: (newValue: T[K]) => {
      if (newValue !== subject.getValue()) {
        subject.next(newValue);
      }
    }
  });
  return subject;
};

export const observeFields = <T extends object>(target: T) => {
  const subjects = {} as { [key: string]: Observable<any> };
  return new Proxy(target, {
    get: (t, prop: string) => {
      if (subjects[prop]) { return subjects[prop]; }
      return subjects[prop] = observeField(t, prop as keyof T).pipe(
        shareReplay({refCount: true, buffer:1}),
      );
    }
  }) as Required<{ [key in keyof T]: Observable<NonNullable<T[key]>> }>;
};

Demo

@Input() set categoryId(categoryId: number) {
      console.log(categoryId)
}

请尝试使用此方法。希望这有帮助

在组件中使用ngOnChanges()生命周期方法。

ngOnChanges在数据绑定财产在检查视图和内容子项之前,如果至少其中一个已经改变了。

这是文件。

此处ngOnChanges将在输入属性更改时始终触发:

ngOnChanges(changes: SimpleChanges): void {
 console.log(changes.categoryId.currentValue)
}