Angular 6组件间通过Service传参遇TS2339错误求助
嘿,我一眼就看出问题所在啦!你遇到的error TS2339: Property 'subscribe' does not exist on type '(data: any) => void'错误,是因为你在接收数据的组件里错误地订阅了服务的方法,而不是订阅正确的Observable对象。
错误原因分析
你的DataTransferService里,setpreviewdata只是一个用来更新BehaviorSubject的普通方法,它的返回值是void,根本不是Observable类型,所以自然不能调用subscribe方法。你真正需要订阅的是服务里暴露出来的datapreview这个Observable(它是从BehaviorSubject转换而来的)。
修复步骤
只需要修改PreviewadComponent的ngOnInit方法,把订阅的目标从setpreviewdata改成datapreview即可:
修改后的PreviewadComponent代码:
import { Component, OnInit } from '@angular/core'; import { DataTransferService } from '../../../dt-broker/dt-core/services/data-transfer.service'; @Component({ selector: 'ngx-previewad', templateUrl: './previewad.component.html', styleUrls: ['./previewad.component.scss'] }) export class PreviewadComponent implements OnInit { constructor(private dataTrans: DataTransferService) { } public result = null; ngOnInit() { // 订阅正确的Observable:datapreview this.dataTrans.datapreview.subscribe(message => this.result = message); } }
额外优化建议(避免内存泄漏)
手动调用subscribe后,如果组件销毁时不取消订阅,可能会导致内存泄漏。推荐两种更优雅的方式:
使用
async管道(推荐)
把result改成Observable类型,在模板中用async管道自动处理订阅和取消:// PreviewadComponent.ts public result$ = this.dataTrans.datapreview;模板中使用:
<!-- previewad.component.html --> <div *ngIf="result$ | async as result"> <!-- 这里渲染你的预览数据,比如 {{ result.someField }} --> </div>手动取消订阅
使用takeUntil操作符,在组件销毁时终止订阅:import { Component, OnInit, OnDestroy } from '@angular/core'; import { DataTransferService } from '../../../dt-broker/dt-core/services/data-transfer.service'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'ngx-previewad', templateUrl: './previewad.component.html', styleUrls: ['./previewad.component.scss'] }) export class PreviewadComponent implements OnInit, OnDestroy { private destroy$ = new Subject<void>(); public result = null; constructor(private dataTrans: DataTransferService) { } ngOnInit() { this.dataTrans.datapreview .pipe(takeUntil(this.destroy$)) .subscribe(message => this.result = message); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } }
补充:类型安全优化
为了让代码更健壮,建议给BehaviorSubject指定明确的类型,比如先定义一个数据接口:
// 可以放在服务文件里或者单独的接口文件中 interface PreviewData { // 这里定义你的预览数据结构,比如: title: string; content: string; // ...其他字段 }
然后修改服务中的BehaviorSubject:
private previewdata = new BehaviorSubject<PreviewData | null>(null); datapreview = this.previewdata.asObservable();
这样TypeScript就能帮你在编译阶段检查数据类型,避免潜在的错误。
内容的提问来源于stack exchange,提问作者sooraj s pillai

