将posts.service移至Angular应用后,如何向库内Title组件传递数据
问题描述
现有一个名为posts-lib的Angular库,原本通过库内的posts.service.ts发起HTTP请求获取文章列表,再由依赖该服务的title.component.ts组件展示内容,当前功能正常。现在要把posts.service.ts移到主应用中,需要实现将主应用中该服务的数据传递给库内的title.component.ts组件。
相关文件代码
title.component.html
<h1>Testing titles api call</h1> <ul> <li *ngFor="let item of data">{{item.title}}</li> </ul>
title.component.ts
import { Component, OnInit } from '@angular/core'; import { PostsService } from '../posts.service'; @Component({ selector: 'lib-tilte', templateUrl: './tilte.component.html', styleUrls: ['./tilte.component.css'] }) export class TilteComponent implements OnInit { data: any; constructor(private postData: PostsService) { } ngOnInit() { this.postData.getPosts().subscribe((result) => { console.warn("reult",result); this.data = result; }) } }
posts-lib.component.ts
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'lib-posts-lib', template: ` <p> posts-lib works! </p> `, styles: [ ] }) export class PostsLibComponent implements OnInit { constructor() { } ngOnInit(): void { } }
posts-lib.module.ts
import { NgModule } from '@angular/core'; import { PostsLibComponent } from './posts-lib.component'; import { TilteComponent } from './tilte/tilte.component'; import { HttpClientModule } from "@angular/common/http"; import { CommonModule } from '@angular/common' @NgModule({ declarations: [ PostsLibComponent, TilteComponent ], imports: [ HttpClientModule, CommonModule ], exports: [ PostsLibComponent, TilteComponent ] }) export class PostsLibModule { }
posts.service.ts
import { Injectable } from '@angular/core'; import { HttpClient } from "@angular/common/http"; @Injectable({ providedIn: 'root' }) export class PostsService { url = "https://jsonplaceholder.typicode.com/posts"; constructor(private http: HttpClient) { } getPosts() { return this.http.get(this.url); } }
public-api.ts
export * from './lib/tilte/tilte.component'; export * from './lib/posts-lib.service'; export * from './lib/posts-lib.component'; export * from './lib/posts-lib.module'; export * from './lib/posts.service';
解决方案
方式一:通过@Input()输入属性传递数据
这是最直接的解耦方式,让组件不再依赖服务,而是接收外部传入的数据:
- 修改库内的
title.component.ts,添加@Input()属性:
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'lib-tilte', templateUrl: './tilte.component.html', styleUrls: ['./tilte.component.css'] }) export class TilteComponent implements OnInit { @Input() data: any; // 接收外部传入的数据 constructor() { } ngOnInit() { // 无需再订阅服务,直接使用传入的data } }
- 主应用中,先通过自身的
PostsService获取数据,再传递给组件:
<!-- 主应用组件模板 --> <lib-tilte [data]="postsData"></lib-tilte>
// 主应用组件TS文件 import { Component, OnInit } from '@angular/core'; import { PostsService } from './posts.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { postsData: any; constructor(private postData: PostsService) { } ngOnInit() { this.postData.getPosts().subscribe((result) => { this.postsData = result; }); } }
方式二:依赖注入适配(保持组件对服务的依赖)
如果希望保留组件的服务依赖逻辑,可通过抽象类解耦,让组件使用主应用提供的服务实例:
- 在库内定义抽象服务类:
// 库内新增文件 abstract-posts.service.ts import { Observable } from 'rxjs'; export abstract class AbstractPostsService { abstract getPosts(): Observable<any>; }
- 修改库内
title.component.ts依赖抽象类:
import { Component, OnInit } from '@angular/core'; import { AbstractPostsService } from './abstract-posts.service'; @Component({ selector: 'lib-tilte', templateUrl: './tilte.component.html', styleUrls: ['./tilte.component.css'] }) export class TilteComponent implements OnInit { data: any; constructor(private postData: AbstractPostsService) { } ngOnInit() { this.postData.getPosts().subscribe((result) => { this.data = result; }) } }
- 主应用的
PostsService实现抽象类:
import { Injectable } from '@angular/core'; import { HttpClient } from "@angular/common/http"; import { AbstractPostsService } from 'posts-lib'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class PostsService implements AbstractPostsService { url = "https://jsonplaceholder.typicode.com/posts"; constructor(private http: HttpClient) { } getPosts(): Observable<any> { return this.http.get(this.url); } }
- 主应用模块中配置依赖映射:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { PostsLibModule } from 'posts-lib'; import { AbstractPostsService } from 'posts-lib'; import { PostsService } from './posts.service'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, PostsLibModule], providers: [ { provide: AbstractPostsService, useClass: PostsService } ], bootstrap: [AppComponent] }) export class AppModule { }
方式三:RxJS Subject跨模块传值
通过主应用服务的Subject广播数据,库组件订阅获取:
- 修改主应用
PostsService:
import { Injectable } from '@angular/core'; import { HttpClient } from "@angular/common/http"; import { Observable, Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class PostsService { url = "https://jsonplaceholder.typicode.com/posts"; private postsSubject = new Subject<any>(); posts$ = this.postsSubject.asObservable(); constructor(private http: HttpClient) { } getPosts() { this.http.get(this.url).subscribe(data => { this.postsSubject.next(data); }); } }
- 库内
title.component.ts订阅数据:
import { Component, OnInit } from '@angular/core'; import { PostsService } from '../../../../src/app/posts.service'; // 根据实际路径调整 @Component({ selector: 'lib-tilte', templateUrl: './tilte.component.html', styleUrls: ['./tilte.component.css'] }) export class TilteComponent implements OnInit { data: any; constructor(private postData: PostsService) { } ngOnInit() { this.postData.posts$.subscribe((result) => { this.data = result; }); this.postData.getPosts(); // 触发数据获取 } }
注:此方式耦合性较高,仅适合简单场景。
内容的提问来源于stack exchange,提问作者Pushpinder Singh
相关产品推荐
相关产品推荐

