Angular项目修改代码刷新页面后,数据获取失效如何解决?
问题解决:选择客户后刷新页面数据无法正常获取
问题描述
实现了客户选择功能:用户选择客户时,将客户ID保存到localStorage,同时通过服务同步状态。但修改代码并刷新页面后,无法正常获取数据,选中状态也异常。相关代码如下:
组件代码
export class AdminDashboardComponent implements OnInit{ widgets = [1, 2, 3, 4]; customers: Customer[] = []; selectedCustomerId!: string | null; constructor(private authService: AuthenticationService, private dbService: DbService, private customerSelectionService: CustomerSelectionService) { } ngOnInit() { this.selectedCustomerId = localStorage.getItem('selectedCustomerId'); if (this.selectedCustomerId) { this.customerSelectionService.setSelectedCustomerId(this.selectedCustomerId); } this.fetchCustomers(); } fetchCustomers() { this.dbService.selectCustomer().subscribe({ next: (data: Customer[]) => { console.log(data); this.customers = data; }, error: (error) => { console.error('Error fetching customers', error); }, complete: () => console.log('Customer fetch completed') }); } onCustomerSelected(event: any) { const customerId = event.value; if (customerId !== null && customerId !== undefined) { this.selectedCustomerId = customerId; localStorage.setItem('selectedCustomerId', customerId.toString()); this.customerSelectionService.setSelectedCustomerId(customerId.toString()); this.dbService.sendCustomerId(customerId).subscribe({ next: (response) => { localStorage.setItem('token', response.token); console.log('Customer ID sent to backend successfully:', response); }, error: (error) => { console.error('Error sending customer ID to backend:', error); } }); } else { console.error('Selected customer ID is null or undefined'); } } logout() { this.authService.logout(); } }
选择功能HTML代码
<div class="selector"> <mat-form-field> <mat-label>Select Customer</mat-label> <mat-select [value]="selectedCustomerId" (selectionChange)="onCustomerSelected($event)"> <mat-option *ngFor="let customer of customers" [value]="customer.customer_id"> {{ customer.customer_name }} </mat-option> </mat-select> </mat-form-field> </div>
客户选择服务代码
export class CustomerSelectionService { private selectedCustomerIdSource = new BehaviorSubject<string | null>(null); selectedCustomerId$ = this.selectedCustomerIdSource.asObservable(); setSelectedCustomerId(customerId: string | null) { this.selectedCustomerIdSource.next(customerId); } }
后端服务代码
selectCustomer(): Observable<any[]> { const httpOptions = { headers: new HttpHeaders({ 'Authorization': 'Bearer ' + localStorage.getItem('token') }) }; return this.http.get<any[]>(this.apiUrl + "/admin-dashboard", httpOptions); }
原因分析
- 类型不匹配:
localStorage存储的是字符串类型,但customer.customer_id可能是数字类型,导致mat-select无法匹配选中项,视觉上显示未选中,进而影响后续数据逻辑。 - 初始化顺序问题:
selectedCustomerId在客户列表加载前就已设置,但此时customers数组为空,mat-select无选项可匹配;客户列表加载完成后,Angular未自动触发变更检测更新选中状态。 - Token 有效性问题:刷新页面时,
selectCustomer接口使用的是页面加载时的旧Token,若该Token未关联所选客户,会导致后端返回的客户列表异常或权限验证失败。
解决方案
1. 统一数据类型,确保选中值匹配
根据customer.customer_id的实际类型,统一selectedCustomerId的类型:
- 若
customer.customer_id为数字类型:// ngOnInit中 const storedId = localStorage.getItem('selectedCustomerId'); this.selectedCustomerId = storedId ? Number(storedId) : null; // onCustomerSelected中 localStorage.setItem('selectedCustomerId', customerId.toString()); this.selectedCustomerId = typeof customerId === 'string' ? Number(customerId) : customerId; - 若
customer.customer_id为字符串类型,确保存储和读取一致:// fetchCustomers回调中转换类型(若后端返回数字) this.customers = data.map(cust => ({...cust, customer_id: cust.customer_id.toString()}));
2. 客户列表加载完成后同步选中状态
修改fetchCustomers,在客户列表加载完成后重新设置选中值,确保mat-select能正确匹配:
fetchCustomers() { this.dbService.selectCustomer().subscribe({ next: (data: Customer[]) => { this.customers = data; // 列表加载完成后读取localStorage并设置选中值 const storedId = localStorage.getItem('selectedCustomerId'); if (storedId) { // 处理类型匹配 this.selectedCustomerId = typeof this.customers[0]?.customer_id === 'number' ? Number(storedId) : storedId; this.customerSelectionService.setSelectedCustomerId(this.selectedCustomerId); } }, error: (error) => { console.error('Error fetching customers', error); }, complete: () => console.log('Customer fetch completed') }); }
同时调整ngOnInit顺序,先加载客户列表再处理选中逻辑:
ngOnInit() { this.fetchCustomers(); }
3. 确保Token与所选客户关联有效
刷新页面时,先刷新关联所选客户的Token,再加载客户列表:
ngOnInit() { const storedId = localStorage.getItem('selectedCustomerId'); if (storedId) { // 先刷新Token,确保权限正确 this.dbService.sendCustomerId(storedId).subscribe({ next: (response) => { localStorage.setItem('token', response.token); this.selectedCustomerId = storedId; this.customerSelectionService.setSelectedCustomerId(storedId); this.fetchCustomers(); }, error: (error) => { console.error('Error refreshing customer token:', error); localStorage.removeItem('selectedCustomerId'); this.fetchCustomers(); } }); } else { this.fetchCustomers(); } }
4. 优化服务初始化逻辑
修改CustomerSelectionService,初始化时直接读取localStorage,减少组件手动同步代码:
export class CustomerSelectionService { private selectedCustomerIdSource = new BehaviorSubject<string | null>( localStorage.getItem('selectedCustomerId') ); selectedCustomerId$ = this.selectedCustomerIdSource.asObservable(); setSelectedCustomerId(customerId: string | null) { this.selectedCustomerIdSource.next(customerId); customerId ? localStorage.setItem('selectedCustomerId', customerId) : localStorage.removeItem('selectedCustomerId'); } }
组件中直接订阅服务的Observable更新视图:
ngOnInit() { this.customerSelectionService.selectedCustomerId$.subscribe(id => { this.selectedCustomerId = id; }); // 其他初始化逻辑... }
内容的提问来源于stack exchange,提问作者mbakgor
相关产品推荐
相关产品推荐

