我有一个父组件(CategoryComponent)、一个子组件(videoListComponent)和一个ApiService。
我的大部分工作都很好,即每个组件都可以访问jsonapi,并通过可观测获取相关数据。
目前,视频列表组件只获取所有视频,我想将其过滤为特定类别中的视频,我通过@Input()将categoryId传递给孩子来实现这一点。
类别组件.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
这是有效的,当父CategoryComponent类别发生更改时,categoryId值将通过@Input()传递,但我需要在VideoListComponent中检测到这一点,并通过APIService(使用新的categoryId)重新请求视频数组。
在AngularJS中,我会对变量进行$watch。处理此问题的最佳方法是什么?
您也可以将EventEmitter作为输入传递。不太确定这是否是最佳实践,尽管。。。
类别组件:
categoryIdEvent: EventEmitter<string> = new EventEmitter<>();
- OTHER CODE -
setCategoryId(id) {
this.category.id = id;
this.categoryIdEvent.emit(this.category.id);
}
类别组件.html:
<video-list *ngIf="category" [categoryId]="categoryIdEvent"></video-list>
在VideoListComponent.ts中:
@Input() categoryIdEvent: EventEmitter<string>
....
ngOnInit() {
this.categoryIdEvent.subscribe(newID => {
this.categoryId = newID;
}
}
您可以在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();
}
角度ngOnChanges
ngOnChanges()是一个内置的Angular回调方法,在默认更改检测器检查数据绑定财产(如果至少有一个属性发生了更改)后立即调用。在视图和内容之前,将检查子级。
// child.component.ts
import { Component, OnInit, Input, SimpleChanges, OnChanges } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges {
@Input() inputParentData: any;
constructor() { }
ngOnInit(): void {
}
ngOnChanges(changes: SimpleChanges): void {
console.log(changes);
}
}
更多信息:Angular Docs
我会坚持采用@alan-c-s建议的方法,但需要做一些修改。首先,我反对使用ngOnChanges。相反,我建议将所有需要更改的内容移到一个对象下。并使用BehaviorSubject跟踪其变化:
private location$: BehaviorSubject<AbxMapLayers.Location> = new BehaviorSubject<AbxMapLayers.Location>(null);
@Input()
set location(value: AbxMapLayers.Location) {
this.location$.next(value);
}
get location(): AbxMapLayers.Location {
return this.location$.value;
}
<abx-map-layer
*ngIf="isInteger(unitForm.get('addressId').value)"
[location]="{
gpsLatitude: unitForm.get('address.gpsLatitude').value,
gpsLongitude: unitForm.get('address.gpsLongitude').value,
country: unitForm.get('address.country').value,
placeName: unitForm.get('address.placeName').value,
postalZip: unitForm.get('address.postalZip').value,
streetName: unitForm.get('address.streetName').value,
houseNumber: unitForm.get('address.houseNumber').value
}"
[inactive]="unitAddressForm.disabled"
>
</abx-map-layer>