Angular 14详情页删除条目后列表组件无法刷新问题求助
Angular 14.2.9 删除条目后列表不刷新问题排查
我在Angular 14.2.9项目里,详情页删除条目后,列表组件没法刷新。已经确认修改了数组引用,但问题还在。我是Angular新手,想问懒加载会导致这个问题吗?
相关代码
服务层(HeroService)
import { EventEmitter, Injectable, Output } from '@angular/core'; import { Hero } from './hero'; import { HEROES } from './mock-heroes'; import { Observable, of } from 'rxjs'; import { MessageService } from './message.service'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Customer } from './customers/Customer'; import {PaginatedResult} from '../app/shared/model/PaginationResult' @Injectable({ providedIn: 'root' }) export class HeroService { @Output() aClickedEvent = new EventEmitter<number>(); constructor(private http: HttpClient, private messageService: MessageService) { } page: number = 0; getHeroes(page: number): Observable<PaginatedResult<Customer>> { if(page !== 0 ) { page = page -1; } return this.http.get<PaginatedResult<Customer>>(`http://localhost:8080/customer?page=${page}&limit=10`) } deleteCustomer(id?: number): Observable<Customer> { this.aClickedEvent.emit(data); return this.http.delete<Customer>('http://localhost:8080/user/' + id); } }
列表组件(HeroesComponent)
import { ChangeDetectionStrategy, Component, NgZone, OnInit } from '@angular/core'; import { HeroService } from '../../hero.service'; import { MessageService } from '../../message.service'; import { Customer } from '../Customer'; @Component({ selector: 'app-heroes', templateUrl: './heroes.component.html', styleUrls: ['./heroes.component.css'], changeDetection: ChangeDetectionStrategy.Default }) export class HeroesComponent implements OnInit { users:Customer[] = []; users2:Customer[] = []; p: number = 0; total: number = 0; constructor(private zone: NgZone,private heroService: HeroService, private messageService: MessageService) { } selectedHero?: Customer; onSelect(hero: Customer): void { this.messageService.add(`HeroesComponent: Selected hero id=${hero.id}`); this.selectedHero = hero; } ngOnInit(): void { this.heroService.aClickedEvent .subscribe((data:number) => { this.users = this.users.filter(a => a.id !== data) console.log(this.users); this.users = [...this.users] }); this.getUsers(); } getUsers(){ this.heroService.getHeroes(this.p) .subscribe((response: any) => { console.log(response); this.users = response.results; this.total = response.totalCount; }); } pageChangeEvent(event: number){ console.log(event); this.p = event; this.getUsers(); } }
列表组件模板(heroes.component.html)
<div class="container" > <div > <table style="float: left" class="table table-bordered st"> <thead> <tr> <th>ID</th> <th>First Name</th> <th>Last Name</th> </tr> </thead> <tbody> <tr *ngFor="let user of users | paginate: { itemsPerPage: 10, currentPage: p, totalItems: total }" routerLink="detail/{{user.id}}"> <td>{{ user.id }}</td> <td>{{ user.firstName }}</td> <td>{{ user.lastName }}</td> </tr> </tbody> </table> <pagination-controls (pageChange)="pageChangeEvent($event)"></pagination-controls> </div> </div>
详情组件(HeroDetailComponent)
import { Component, OnInit, Input } from '@angular/core'; import { Customer } from '../Customer'; import { ActivatedRoute } from '@angular/router'; import { Location } from '@angular/common'; import { HeroService } from 'src/app/hero.service'; @Component({ selector: 'app-hero-detail', templateUrl: './hero-detail.component.html', styleUrls: ['./hero-detail.component.css'] }) export class HeroDetailComponent implements OnInit { @Input() customer?: Customer; constructor(private route: ActivatedRoute, private heroService: HeroService, private location: Location) { } ngOnInit(): void { this.getCustomer(); } getCustomer(): void { const id = Number(this.route.snapshot.paramMap.get('id')); this.heroService.getCustomer(id) .subscribe(customer => this.customer = customer); } goBack(): void { this.location.back(); } delete(id?:number):void { this.heroService.deleteCustomer(id) .subscribe(string => {}); this.location.back(); } edit() { } }
详情组件模板(hero-detail.component.html)
<div class="container"> <div *ngIf="customer" > <div class="card" style="max-width: 550px; margin-left: 25%;"> <h2 style="text-align:center;"><b>{{customer.firstName}} {{customer.lastName}}</b></h2> <p style="text-align:center;">Address</p> <h2 style="text-align:center;"><b>{{customer?.address?.street}} {{customer.lastName}}</b></h2> <div class="container"> <button class="btn btn-primary btn-lg" type="button" (click)="goBack()" style="margin-left:40px">Back</button> <button class="btn btn-primary btn-lg" type="detai" (click)="edit()" style="margin-left:100px">Edit</button> <button class="btn btn-primary btn-lg" type="button" (click)="delete(customer!.id)" style="margin-left:100px">Delete</button> </div> </div> </div> </div>
问题分析与修复
1. 先明确:懒加载不是当前问题的原因
懒加载只会影响模块的加载时机,不会导致组件数据刷新失败,所以可以排除这个因素。
2. 代码里的核心问题
(1)服务层事件触发参数错误
在HeroService的deleteCustomer方法里,this.aClickedEvent.emit(data);中的data是未定义的变量,应该传入要删除的id,否则列表组件的过滤逻辑根本找不到要移除的条目。
修复:
deleteCustomer(id?: number): Observable<Customer> { this.aClickedEvent.emit(id); // 把data改成id return this.http.delete<Customer>('http://localhost:8080/user/' + id); }
(2)异步操作时序错误
详情页的delete方法里,调用deleteCustomer后立刻执行location.back(),但HTTP请求是异步的,可能事件还没触发就已经返回列表页了,导致列表组件的订阅没收到事件。
修复:把返回操作移到订阅回调里,确保删除请求完成后再返回:
delete(id?:number):void { this.heroService.deleteCustomer(id) .subscribe(() => { this.location.back(); // 移到回调内,保证事件已触发 }); }
(3)组件销毁导致订阅失效(潜在问题)
如果列表组件在路由切换时被销毁(比如从详情页返回时组件重建),那么之前在ngOnInit里的事件订阅就会失效,这时候即使触发了事件,新的组件实例也接收不到。
更可靠的替代方案:
去掉服务层的EventEmitter和列表页的订阅逻辑,改为每次进入列表页时重新拉取数据。比如在列表组件的ngOnInit里固定调用getUsers(),这样每次进入列表页都会获取最新数据,完全不用依赖事件传递。
3. 额外优化点
如果删除的是当前页的最后一条数据,需要调整页码并重新拉取,避免出现空页。可以在删除后判断当前列表长度,如果为空且页码大于1,就把页码减1再调用getUsers()。
内容的提问来源于stack exchange,提问作者Thomas124124
相关产品推荐
相关产品推荐

