Angular上传图片后canvas的background.src未更新如何用Observable解决
解决方案
方案1:使用Observable实现跨组件通知
核心是通过共享服务创建通知流,上传成功后主动推送更新事件给第一个组件:
- 首先修改共享的
srcService,新增图片更新通知流:
import { Injectable } from '@angular/core'; import { Subject, takeUntil } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SrcService { // 私有Subject,避免外部直接修改 private imgUpdatedSubject = new Subject<void>(); // 对外暴露的可订阅流 public imgUpdated$ = this.imgUpdatedSubject.asObservable(); // 上传成功后调用该方法触发更新通知 public triggerImgUpdate() { this.imgUpdatedSubject.next(); } // 原有getImgURL方法保留 getImgURL(id: string) { // 原有逻辑 return `https://something.com/image/${id}`; } }
- 修改第一个组件,将
background提升为类属性,订阅更新通知:
export class FirstComponent implements AfterViewInit, OnDestroy { @ViewChild('canvas', { static: true }) canvas: ElementRef<HTMLCanvasElement>; // 提升为类属性,方便后续修改 private background: HTMLImageElement; private destroy$ = new Subject<void>(); src: string; constructor(private srcService: SrcService) {} ngAfterViewInit() { this.background = new Image(); this.loadBackgroundSrc(); // 订阅图片更新通知,收到通知后重新加载src this.srcService.imgUpdated$ .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.loadBackgroundSrc(); }); } // 抽离加载src的公共方法 private loadBackgroundSrc() { this.src = this.srcService.getImgURL(this.id); this.background.src = this.src; } ngOnDestroy() { // 清理订阅避免内存泄漏 this.destroy$.next(); this.destroy$.complete(); } }
- 修改第二个组件,上传成功后触发通知:
export class SecondComponent { constructor( @Inject(MAT_DIALOG_DATA) public data: IInterface, public dialogRef: MatDialogRef<SettingsComponent>, private srcService: SrcService ) {} // 你的图片上传成功回调方法 onUploadSuccess() { // 上传成功后先触发更新通知 this.srcService.triggerImgUpdate(); // 再关闭弹窗 this.dialogRef.close(true); } close() { this.dialogRef.close(false); } }
方案2:无需Observable的替代方案(利用Dialog关闭回调)
如果不想额外维护服务里的Observable流,可以直接利用Angular Material Dialog自带的afterClosed回调实现:
- 首先修改第一个组件中打开弹窗的逻辑,订阅弹窗关闭事件,判断如果上传成功就重新加载src:
// 第一个组件中打开SecondComponent的代码 openUploadDialog() { const dialogRef = this.dialog.open(SecondComponent, { // 你的弹窗配置 }); // 订阅弹窗关闭回调 dialogRef.afterClosed().subscribe((uploadSuccess: boolean) => { // 如果返回true代表上传成功,重新加载背景图src if (uploadSuccess) { this.loadBackgroundSrc(); } }); } // 抽离loadBackgroundSrc方法,和方案1一致 private loadBackgroundSrc() { this.src = this.srcService.getImgURL(this.id); this.background.src = this.src; }
- 第二个组件只需在上传成功后关闭弹窗时返回
true即可,无需注入服务:
// 第二个组件的上传成功回调 onUploadSuccess() { this.dialogRef.close(true); }
该方案无需额外维护Observable流,适合只有这两个组件依赖图片更新的场景。
内容的提问来源于stack exchange,提问作者Arter
相关产品推荐
相关产品推荐

