Ionic5+Angular12 @Input+Modal嵌套场景父级Observable List不更新问题
问题根因
- 当前
getAllServiceRequests仅在RequestTabPage初始化时触发一次,服务端数据更新后没有机制通知前端刷新本地列表 app-request-long的ngOnChanges仅在@Input() serviceRequests的数组引用发生变化时才会触发,仅修改数组内部某一项的status属性不会触发变化检测,也就不会重新执行排序逻辑
具体实现方案
提供两种可选实现方式,可根据业务场景选择:
方案1:全局数据通知(适合多页面共享服务请求数据的场景)
改造ServiceRequestService新增全局数据同步能力,所有数据修改后自动同步到所有订阅页面:
// serviceRequestService.ts 新增代码 private serviceRequestsSubject = new BehaviorSubject<ServiceRequest[]>([]); public serviceRequests$ = this.serviceRequestsSubject.asObservable(); // 修改原getAllServiceRequests方法,拉取数据后更新全局通知 getAllServiceRequests(): Observable<ServiceRequest[]> { // 保留原有http请求逻辑,请求成功后新增如下代码 this.http.get<ServiceRequest[]>(你的原请求地址).subscribe(res => { this.serviceRequestsSubject.next(res); }); return this.serviceRequests$; } // 修改updateServiceRequestById方法,更新成功后刷新全局数据 updateServiceRequestById(serviceRequest: ServiceRequest): Promise<ServiceRequest> { const API_URL = `${this.serviceRequestJSON}/${serviceRequest.id}`; const header = new HttpHeaders().set('Content-Type', 'application/json'); return this.http.put<ServiceRequest>(API_URL, serviceRequest, {headers: header}).toPromise() .then(updatedReq => { // 更新成功后重新拉取全量列表同步到全局 this.getAllServiceRequests(); return updatedReq; }); }
同时优化app-request-long的输入监听逻辑,避免漏触发更新:
// app-request-long.component.ts // 用setter替代ngOnChanges,只要输入值有变化就自动重排 @Input() set serviceRequests(val: ServiceRequest[]) { this._serviceRequests = val; this.sortByStatus(val); } private _serviceRequests: ServiceRequest[];
方案2:局部事件冒泡(适合仅当前页面需要更新的场景,减少接口请求)
通过Modal回传+组件事件冒泡的方式,仅更新当前页面的列表数据:
- 首先修改Modal代码,关闭时回传更新后的请求数据
// Modal组件ts代码 scheduled(request: ServiceRequest){ if(request.status === ReqStatus.pending){ request.status = ReqStatus.scheduled; } this.requestService.updateServiceRequestById(request).then((resp)=>{ // 关闭时携带更新后的请求数据 this.modalController.dismiss({ dismissed: true, updatedRequest: resp }); }); }
- 在
app-request-short中监听Modal关闭事件,向上抛出更新事件
// app-request-short.component.ts @Output() requestUpdated = new EventEmitter<ServiceRequest>(); private async presentModal(){ const modal = await this.modalController.create({ component: ServiceRequestDetailsPage, backdropDismiss:true, showBackdrop:true, componentProps:{ request: this.serviceRequest } }); // 监听Modal关闭返回结果 modal.onDidDismiss().then(res => { if(res.data?.updatedRequest) { this.requestUpdated.emit(res.data.updatedRequest); } }); return await modal.present(); }
- 在
app-request-long中接收事件,更新本地列表并重排
<!-- app-request-long.component.html 给所有app-request-short绑定事件 --> <app-request-short style='width: 100%;' [serviceRequest]='request' [requestedDate]='request.requestedDate' (requestUpdated)="handleRequestUpdate($event)" ></app-request-short>
// app-request-long.component.ts 新增更新处理逻辑 handleRequestUpdate(updatedReq: ServiceRequest) { // 替换对应项生成新数组,触发引用变化让变化检测生效 this.serviceRequests = this.serviceRequests.map(req => req.id === updatedReq.id ? updatedReq : req ); // 手动触发排序 this.sortByStatus(this.serviceRequests); }
内容的提问来源于stack exchange,提问作者Idea
相关产品推荐
相关产品推荐

