Angular兄弟组件间收据数据传递失败求助
问题分析与解决方案
核心问题
- Service非单例:Create组件的
providers: [ReceiptdataService]会让组件实例化独立的Service实例,导致Create和Check组件使用的不是同一个Service,Subject消息无法跨组件传递。 - 未触发Subject发送:Create组件的
inputData方法只调用了AddNewReceipt,没有触发Service的消息推送逻辑。 - 普通Subject的局限性:普通Subject仅能接收订阅之后发送的消息,Check组件初始化时无法获取已存在的收据数据。
分步修复
1. 修正Service为单例模式并优化消息推送
改用BehaviorSubject保存最新收据列表,确保新订阅组件能获取历史数据,同时设置全局单例:
import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' // 全局单例,全应用共享同一个实例 }) export class ReceiptdataService { receipts = [ {cusName:"Barka",buyDate:"2019-01-23",realDate:"2020-12-21",product:"macska",cusComment:"NEm tetszik",prodPrice:233423} ]; // BehaviorSubject保存当前收据列表,初始值为已有数据 private receiptSubject = new BehaviorSubject<any[]>(this.receipts); receipt$ = this.receiptSubject.asObservable(); addNewReceipt(name:string, date:string,date2:string,item:string,comment:string,price:number){ const newReceipt = {cusName:name ,buyDate:date,realDate:date2,product:item,cusComment:comment,prodPrice:price}; this.receipts.push(newReceipt); // 推送更新后的完整列表,触发订阅组件更新 this.receiptSubject.next([...this.receipts]); // 生成新数组确保变更检测生效 } }
2. 修正Create组件
移除组件内的Service提供者,确保使用全局单例:
import { ReceiptdataService } from 'src/app/receiptdata.service'; import { Router } from '@angular/router'; import { OnInit } from '@angular/core'; @Component({ selector: 'app-create', templateUrl: './create.component.html', styleUrls: ['./create.component.css'] // 移除 providers: [ReceiptdataService],避免创建局部Service实例 }) export class CreateComponent implements OnInit { cusName:string=""; buyDate:string=""; realDate:string=""; product:string=""; cusComment:string=""; prodPrice:number=0; constructor(private router: Router,private receiptdataService: ReceiptdataService) { } ngOnInit(): void {} inputData(){ this.receiptdataService.addNewReceipt( this.cusName, this.buyDate, this.realDate, this.product, this.cusComment, this.prodPrice ); // 可选:提交后清空表单 this.cusName = ""; this.buyDate = ""; this.realDate = ""; this.product = ""; this.cusComment = ""; this.prodPrice = 0; } }
3. 修正Check组件
订阅Service的receipt$获取完整收据列表,并在组件销毁时取消订阅防止内存泄漏:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router } from '@angular/router'; import { ReceiptdataService } from 'src/app/receiptdata.service'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-check', templateUrl: './check.component.html', styleUrls: ['./check.component.css'] }) export class CheckComponent implements OnInit, OnDestroy { subscription: Subscription; receipts: any[] = []; constructor(private router: Router,private receiptdataService: ReceiptdataService) { } ngOnInit(): void { this.subscription = this.receiptdataService.receipt$.subscribe(res => { this.receipts = res; // 直接赋值完整列表 console.log('当前收据列表:', res); }); } ngOnDestroy(): void { // 销毁订阅,避免内存泄漏 this.subscription.unsubscribe(); } }
4. Check组件HTML表格展示示例
在模板中遍历receipts数组渲染表格:
<table border="1"> <thead> <tr> <th>客户姓名</th> <th>购买日期</th> <th>实际日期</th> <th>产品</th> <th>客户评价</th> <th>价格</th> </tr> </thead> <tbody> <tr *ngFor="let item of receipts"> <td>{{ item.cusName }}</td> <td>{{ item.buyDate }}</td> <td>{{ item.realDate }}</td> <td>{{ item.product }}</td> <td>{{ item.cusComment }}</td> <td>{{ item.prodPrice }}</td> </tr> </tbody> </table>
内容的提问来源于stack exchange,提问作者Rebeka Süveges
相关产品推荐
相关产品推荐

