Angular 5+组件通信的两种实现方式及选型疑问
咱们先梳理下这两种Angular组件通信的实现方式,再聊聊哪个更值得选,以及RxJS是不是过度设计的问题。
方法1:直接使用服务中的共享数组
data.service.ts
import { Injectable } from '@angular/core'; @Injectable() export class DataService { people: Array<any> = [ { name: 'David', role: 'King of Israel' }, { name: 'Daniel', role: 'Major Prophet' } ]; state = { msg: '' } constructor() { console.log(this.people) } }
app.component.ts
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent implements OnInit { people: Array<Object>; state; constructor(private dataService: DataService) {} ngOnInit() { this.people = this.dataService.people; this.state = this.dataService.state; } load() { this.dataService.people.push({name: 'Obadiah', role: 'Minor Prophet'}); } }
app.component.html
<ul> <li *ngFor="let person of people">{{person.name}} | {{person.role}}</li> </ul> <button (click)="load()">Load Additional Data</button> <pre>{{state.msg}}</pre>
方法2:使用RxJS Subjects实现响应式通信
data.service.ts
@Injectable() export class DataService { url = 'http://localhost:3000/Data'; dataStream$ = new Subject<MyModel[]>(); messages: string[] = []; subscription; httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Cache-control': 'no-cache' }) }; constructor(private http: HttpClient) { } get() { this.subscription = this.http.get<any[]>(this.url).subscribe(data => this.dataStream$.next(data)); } post(obj: MyModel) { this.subscription = this.http.post<any>(this.url, obj, this.httpOptions) .subscribe( res => this.get(), err => this.messages.push(err), () => this.messages.push(`'${obj.title}' added`) ); } }
app.component.ts
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent implements OnInit { dataStream$ = new Subject<any>(); messages: string[] = []; obj = { title: 'Epsilon', body: 'Lorem ipsum...' } constructor(private dataService: DataService) {} ngOnInit() { this.dataStream$ = this.dataService.dataStream$; this.dataService.get(); this.messages = this.dataService.messages; } post(){ this.dataService.post(this.obj); } }
app.component.html
<pre>Messages: {{ messages | json }}</pre> <pre>Data:{{ dataStream$ | async | json }}</pre> <button (click)="post()">Add Post</button>
哪种方法更值得推荐?原因是什么?
这得结合你的业务场景来看,但方法2在绝大多数实际项目中更值得推荐,原因如下:
- 封装性与可控性:方法1直接暴露了服务里的数组,任何组件都能随意修改数组内容,很容易导致状态混乱,排查问题时也很难定位是谁修改了数据。而方法2把数据的读写逻辑都封装在服务里,组件只能通过调用
get()、post()方法来操作数据,状态变更完全可控。 - 响应式变更通知:方法1的数组是普通JS数组,当数组内容变化时,组件不会自动收到通知(除非手动用
ngDoCheck监听,这会增加性能开销)。方法2用Subject实现了发布-订阅模式,只要数据有更新,所有订阅了dataStream$的组件都会实时收到新数据,配合Angular的async管道还能自动管理订阅,避免内存泄漏。 - 异步场景适配:如果你的数据来自HTTP请求、WebSocket这类异步操作,方法1很难优雅处理——你得手动在组件里订阅请求,然后更新数组,还得处理订阅清理。方法2天生适配异步数据流,HTTP请求的结果可以直接通过Subject推送给所有订阅者,逻辑更清晰。
当然,如果是非常简单的静态数据共享(比如固定的配置项,不会变更),方法1足够用,代码更简洁。
如此使用RxJS是否属于过度设计?
这同样看场景:
- 如果你的应用只是小Demo,或者只是共享少量不会变化的静态数据,那用RxJS确实有点“小题大做”,属于过度设计,方法1更轻便。
- 但在中大型Angular应用里,这种用法完全不算过度设计:
- Angular本身就深度集成了RxJS(比如
HttpClient返回的就是Observable,@Output本质也是EventEmitter——一种特殊的Subject),用RxJS和Angular的生态完全契合。 - RxJS提供了大量操作符(比如
map、filter、switchMap),能轻松处理复杂的数据流逻辑(比如合并多个请求、过滤重复数据、延迟触发等),这些逻辑用原生JS实现会非常繁琐且容易出错。 - 响应式的数据流模式能让状态变化更可预测,尤其是在多组件共享状态时,能大幅降低组件间的耦合度。
- Angular本身就深度集成了RxJS(比如
内容的提问来源于stack exchange,提问作者user1052888
相关产品推荐
相关产品推荐

