Angular中如何不刷新整页仅重新加载视图?
问题描述
我有一个父组件和两个子组件,其中add-friend子组件需要更新父组件的视图。我编写了receiveReloadFriendLists()方法,日志能正常输出,但视图始终不更新——当前应展示好友列表。我不想刷新页面,因为页面上有正在运行的动画,刷新会中断动画。怀疑是父组件存在遗漏或操作错误,查阅Stack Overflow相关回答后仍未解决问题。
父组件代码
@Component({ selector: 'app-friends', templateUrl: './friends.component.html' }) export class FriendsComponent implements OnInit { requested$: Observable<RelationResponse[]>; requested: RelationResponse[] = []; constructor( private store: Store, private router: Router, private appStore: Store<AppState>, private _fb: FormBuilder ) { this.requested$ = this.store.select(selectRequestedRelationResponse); } ngOnInit(): void { this.getRequestedRelations(); } private getRequestedRelations() { this.store.dispatch(invokeFindRequestedRelations({ userId: StorageUtil.getUserId(), relationStatusRequest: RelationStatusRequest.REQUESTED }) ); this.appStore.pipe(select(selectAppState)).subscribe((appState) => { if (ApiUtil.ifApiStatusIsSuccessReset(appState, this.appStore)) { this.requested$.subscribe((relationResponses) => { this.requested = relationResponses; }) } } ); } receiveReloadFriendLists() { console.log("reload"); this.getRequestedRelations(); } }
父组件HTML
<app-add-friend (reloadRelationsEvent)="receiveReloadFriendLists()" class="p-0"></app-add-friend> <app-relation-list class="p-0" [show]=hasFriendRequests() showHeadline="Friend requests" noShowHeadline="No Friend requests" [relations]="requested" [enableAccept]="true" [enableBlock]="true" [enableDelete]="true"></app-relation-list>
子组件-添加好友
@Component({ selector: 'app-add-friend', templateUrl: './add-friend.component.html' }) export class AddFriendComponent { @Output() reloadRelationsEvent = new EventEmitter<void>(); @ViewChild('sendFriendRequestCallout') sendFriendRequestCallout!: CalloutComponent; addFriendForm: FormGroup; constructor(private _fb: FormBuilder, private store: Store) { this.addFriendForm = this.createAddFriendForm(); } public createAddFriendForm(): FormGroup { ... } sendFriendRequest() { .... } reloadFriendLists() { this.reloadRelationsEvent.emit(); } }
子组件-展示好友
@Component({ selector: 'app-relation-list', templateUrl: './relation-list.component.html' }) export class RelationListComponent { @Input() show: boolean = false; @Input() showHeadline: string = ''; @Input() noShowHeadline: string = ''; @Input() relations: RelationResponse[] = []; @Input() enableAccept: boolean = false; @Input() enableBlock: boolean = false; @Input() enableDelete: boolean = false; ... }
子组件-展示好友HTML
<div class="card p-3 mt-3"> <h5 class="card-title">{{ showHeadline }}</h5> <ng-container *ngFor="let relation of relations"> {{relation.contactUsername }} </ng-container> </div>
问题分析与解决方案
核心问题
- 嵌套订阅时机错误:当
appStore返回成功状态时才去订阅requested$,但此时store.dispatch触发的状态更新可能已完成,新订阅无法捕获到最新数据。 - 重复订阅内存泄漏:每次调用
getRequestedRelations都会新增订阅,导致内存泄漏和不可预期的赋值行为。 - 手动赋值可能未触发变更检测:即使
requested更新,订阅时机错误也会导致视图无法同步。
方案1:使用Async管道(推荐)
直接用Angular的async管道绑定Observable,无需手动维护数组,自动处理订阅和变更检测。
修改父组件
@Component({ selector: 'app-friends', templateUrl: './friends.component.html' }) export class FriendsComponent implements OnInit { requested$: Observable<RelationResponse[]>; constructor( private store: Store, private router: Router, private appStore: Store<AppState>, private _fb: FormBuilder ) { this.requested$ = this.store.select(selectRequestedRelationResponse); } ngOnInit(): void { this.getRequestedRelations(); } private getRequestedRelations() { this.store.dispatch(invokeFindRequestedRelations({ userId: StorageUtil.getUserId(), relationStatusRequest: RelationStatusRequest.REQUESTED }) ); // 移除嵌套订阅,API状态处理可单独在effect或其他逻辑中完成 } receiveReloadFriendLists() { console.log("reload"); this.getRequestedRelations(); } }
修改父组件HTML
将[relations]="requested"替换为[relations]="requested$ | async":
<app-add-friend (reloadRelationsEvent)="receiveReloadFriendLists()" class="p-0"></app-add-friend> <app-relation-list class="p-0" [show]=hasFriendRequests() showHeadline="Friend requests" noShowHeadline="No Friend requests" [relations]="requested$ | async" [enableAccept]="true" [enableBlock]="true" [enableDelete]="true"></app-relation-list>
方案2:修复手动订阅逻辑
若坚持手动维护数组,需正确管理订阅,避免嵌套和泄漏:
import { Subject } from 'rxjs'; import { takeUntil, take } from 'rxjs/operators'; @Component({ selector: 'app-friends', templateUrl: './friends.component.html' }) export class FriendsComponent implements OnInit, OnDestroy { requested$: Observable<RelationResponse[]>; requested: RelationResponse[] = []; private destroy$ = new Subject<void>(); constructor( private store: Store, private router: Router, private appStore: Store<AppState>, private _fb: FormBuilder ) { this.requested$ = this.store.select(selectRequestedRelationResponse); } ngOnInit(): void { // 提前订阅requested$,持续监听数据变化 this.requested$.pipe(takeUntil(this.destroy$)).subscribe((relationResponses) => { this.requested = relationResponses; }); this.getRequestedRelations(); } private getRequestedRelations() { this.store.dispatch(invokeFindRequestedRelations({ userId: StorageUtil.getUserId(), relationStatusRequest: RelationStatusRequest.REQUESTED }) ); // 单独处理API状态,只取一次成功状态后取消订阅 this.appStore.pipe( select(selectAppState), takeUntil(this.destroy$), take(1) ).subscribe((appState) => { ApiUtil.ifApiStatusIsSuccessReset(appState, this.appStore); }); } receiveReloadFriendLists() { console.log("reload"); this.getRequestedRelations(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } }
额外检查项
- 确认
selectRequestedRelationResponse选择器能正确返回更新后的store状态; - 检查
ApiUtil.ifApiStatusIsSuccessReset方法是否影响了store状态的正常更新。
内容的提问来源于stack exchange,提问作者Bianca
相关产品推荐
相关产品推荐

