You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular12如何将组件@Input值传入注入服务,是否应使用ServiceFactory模式

Angular 12 动态将组件Input值注入对应服务实例实现方案

步骤1:调整DataStorageService配置与定义

首先移除服务的全局单例配置,新增dataType注入令牌,修正方法定义同时支持泛型适配不同的Item扩展类型:

import { InjectionToken } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Item } from '你的Item接口路径';

// 定义注入令牌,用于传递dataType参数
export const DATA_TYPE = new InjectionToken<string>('DATA_TYPE');

// 移除providedIn: 'root',不再使用全局单例
@Injectable()
// 泛型约束适配不同Item扩展接口
export class DataStorageService<T extends Item> {
  // 若存在异步赋值场景可改为getter:private get apiEndpoint()
  private readonly apiEndpoint: string;

  constructor(
    @Inject(DATA_TYPE) private readonly dataType: string,
    private http: HttpClient
  ) {
    this.apiEndpoint = environment.config.urlLogin + '/api/' + this.dataType;
  }

  // 移除原代码多余的string参数
  fetchAll(): Observable<T[]> {
    return this.http.get<T[]>(this.apiEndpoint);
  }
}

步骤2:配置ListComponent组件级服务提供者

在组件的providers数组中通过工厂模式配置,实现每个组件实例对应独立的服务实例,自动注入当前组件的dataType输入值:

import { Component, Input, OnInit } from '@angular/core';
import { DataStorageService, DATA_TYPE } from '你的服务路径';
import { HttpClient } from '@angular/common/http';
import { Item } from '你的Item接口路径';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.less'],
  // 组件级注册服务,每个<app-list>实例对应独立的服务实例
  providers: [
    {
      provide: DATA_TYPE,
      useFactory: (component: ListComponent) => component.dataType,
      deps: [ListComponent]
    },
    {
      provide: DataStorageService,
      useFactory: (dataType: string, http: HttpClient) => new DataStorageService(dataType, http),
      deps: [DATA_TYPE, HttpClient]
    }
  ]
})
export class ListComponent implements OnInit {
  @Input() dataType: string;
  items: Item[] = [];

  constructor(private ds: DataStorageService) { }

  ngOnInit(): void {
    // 修正原代码直接赋值Observable的错误,需订阅获取返回值
    this.ds.fetchAll().subscribe(res => {
      this.items = res;
    });
  }
}

步骤3:使用方式

直接传入dataType属性即可,无需额外传参:

<app-list data-type="products"></app-list>
<app-list data-type="orders"></app-list>

不同实例的DataStorageService会自动对应各自的dataType生成接口地址,互不干扰。

泛型扩展适配(可选)

如果需要针对不同dataType使用对应的扩展接口(比如Product extends Item),可以将ListComponent也改为泛型组件:

export class ListComponent<T extends Item> implements OnInit {
  @Input() dataType: string;
  items: T[] = [];

  constructor(private ds: DataStorageService<T>) { }
  // 其余逻辑保持不变
}

注意:如果存在dataType异步赋值的场景,可将DataStorageService中的apiEndpoint改为getter属性,避免初始化时输入值还未赋值导致接口地址错误。

内容的提问来源于stack exchange,提问作者LBA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:45:05