Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计通过

angular-dependency-injectionAngular dependency injection 前端

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

824

周安装

34

GitHub Stars

142

下载量

269
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:angular-dependency-injection(Angular dependency injection 前端)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/angular-dependency-injection
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill angular-dependency-injection
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill angular-dependency-injection

简介

用于辅助前端页面、组件、样式和交互逻辑的开发与维护,适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码。

  • 适用于 Angular 依赖注入系统的模块化设计和可测试性提升,需结合现有架构使用。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装,需结合原始 README 核验具体用法和功能边界。
  • 涉及页面改动时应配合本地预览和构建检查确认视觉效果,避免只生成孤立片段。
  • angular-dependency-injection 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Angular Dependency Injection

Master Angular's dependency injection system for building modular, testable applications with proper service architecture.

DI Fundamentals

Angular's DI is hierarchical and uses decorators and providers:

import { Injectable } from '@angular/core';

// Service injectable at root level
@Injectable({
  providedIn: 'root'
})
export class UserService {
  private users: User[] = [];

  getUsers(): User[] {
    return this.users;
  }

  addUser(user: User): void {
    this.users.push(user);
  }
}

// Component injection
import { Component } from '@angular/core';

@Component({
  selector: 'app-user-list',
  template: `
    <div *ngFor="let user of users">
      {{ user.name }}
    </div>
  `
})
export class UserListComponent {
  users: User[];

  constructor(private userService: UserService) {
    this.users = this.userService.getUsers();
  }
}

Provider Types

useClass - Class Provider

import { Injectable, Provider } from '@angular/core';

// Interface
interface Logger {
  log(message: string): void;
}

// Implementations
@Injectable()
export class ConsoleLogger implements Logger {
  log(message: string): void {
    console.log(message);
  }
}

@Injectable()
export class FileLogger implements Logger {
  log(message: string): void {
    // Write to file
  }
}

// Provider configuration
const loggerProvider: Provider = {
  provide: Logger,
  useClass: ConsoleLogger // or FileLogger based on env
};

// In module
@NgModule({
  providers: [loggerProvider]
})
export class AppModule {}

// Usage
export class MyComponent {
  constructor(private logger: Logger) {
    this.logger.log('Component initialized');
  }
}

useValue - Value Provider

import { InjectionToken } from '@angular/core';

// Configuration object
export interface AppConfig {
  apiUrl: string;
  timeout: number;
  retries: number;
}

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

// Provider
const configProvider: Provider = {
  provide: APP_CONFIG,
  useValue: {
    apiUrl: 'https://api.example.com',
    timeout: 5000,
    retries: 3
  }
};

// Module
@NgModule({
  providers: [configProvider]
})
export class AppModule {}

// Usage
export class ApiService {
  constructor(@Inject(APP_CONFIG) private config: AppConfig) {
    console.log(this.config.apiUrl);
  }
}

useFactory - Factory Provider

import { Injectable, InjectionToken } from '@angular/core';

export const API_URL = new InjectionToken<string>('api.url');

// Factory function
export function apiUrlFactory(config: AppConfig): string {
  return config.production
    ? 'https://api.prod.example.com'
    : 'https://api.dev.example.com';
}

// Provider
const apiUrlProvider: Provider = {
  provide: API_URL,
  useFactory: apiUrlFactory,
  deps: [AppConfig] // Dependencies for factory
};

// Complex factory with multiple deps
export function httpClientFactory(
  handler: HttpHandler,
  config: AppConfig,
  logger: Logger
): HttpClient {
  logger.log('Creating HTTP client');
  return new HttpClient(handler);
}

const httpClientProvider: Provider = {
  provide: HttpClient,
  useFactory: httpClientFactory,
  deps: [HttpHandler, AppConfig, Logger]
};

useExisting - Alias Provider

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class NewLogger {
  log(message: string): void {
    console.log('[NEW]', message);
  }
}

// Alias old logger to new logger
const oldLoggerProvider: Provider = {
  provide: 'OldLogger',
  useExisting: NewLogger
};

// Usage
export class MyComponent {
  constructor(
    @Inject('OldLogger') private logger: NewLogger
  ) {
    this.logger.log('Using aliased logger');
  }
}

Injection Tokens

InjectionToken - Type-Safe Tokens

import { InjectionToken } from '@angular/core';

// Primitive token
export const MAX_RETRIES = new InjectionToken<number>('max.retries', {
  providedIn: 'root',
  factory: () => 3 // Default value
});

// Object token
export interface FeatureFlags {
  enableNewUI: boolean;
  enableBeta: boolean;
}

export const FEATURE_FLAGS = new InjectionToken<FeatureFlags>(
  'feature.flags',
  {
    providedIn: 'root',
    factory: () => ({
      enableNewUI: false,
      enableBeta: false
    })
  }
);

// Usage
@Injectable()
export class ApiService {
  constructor(
    @Inject(MAX_RETRIES) private maxRetries: number,
    @Inject(FEATURE_FLAGS) private flags: FeatureFlags
  ) {}
}

String Tokens (Legacy)

// Not type-safe, avoid when possible
const providers: Provider[] = [
  { provide: 'API_URL', useValue: 'https://api.example.com' },
  { provide: 'TIMEOUT', useValue: 5000 }
];

// Usage
export class MyService {
  constructor(
    @Inject('API_URL') private apiUrl: string,
    @Inject('TIMEOUT') private timeout: number
  ) {}
}

Hierarchical Injectors

Root Injector

// Singleton across entire app
@Injectable({
  providedIn: 'root'
})
export class GlobalService {
  private state = {};
}

// Same instance everywhere

Module Injector

@Injectable()
export class ModuleService {
  // Service specific to module
}

@NgModule({
  providers: [ModuleService]
})
export class FeatureModule {}

// Different instance per module

Component Injector

@Injectable()
export class ComponentService {
  private data = [];
}

@Component({
  selector: 'app-my-component',
  template: '...',
  providers: [ComponentService] // New instance per component
})
export class MyComponent {
  constructor(private service: ComponentService) {}
}

// Each component instance gets its own service instance

Element Injector

@Directive({
  selector: '[appHighlight]',
  providers: [DirectiveService]
})
export class HighlightDirective {
  constructor(private service: DirectiveService) {}
}

// Each directive instance gets its own service

ProvidedIn Options

// Root - singleton
@Injectable({
  providedIn: 'root'
})
export class RootService {}

// Platform - shared across multiple apps
@Injectable({
  providedIn: 'platform'
})
export class PlatformService {}

// Any - new instance per module
@Injectable({
  providedIn: 'any'
})
export class AnyService {}

// Module - specific module
@Injectable({
  providedIn: FeatureModule
})
export class FeatureService {}

Multi-Providers

import { InjectionToken } from '@angular/core';

// Token for multiple providers
export const HTTP_INTERCEPTORS =
  new InjectionToken<HttpInterceptor[]>('http.interceptors');

// Multiple implementations
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // Add auth header
    return next.handle(req);
  }
}

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // Log request
    return next.handle(req);
  }
}

// Register as multi-providers
const providers: Provider[] = [
  {
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true
  },
  {
    provide: HTTP_INTERCEPTORS,
    useClass: LoggingInterceptor,
    multi: true
  }
];

// Inject as array
export class HttpService {
  constructor(
    @Inject(HTTP_INTERCEPTORS) private interceptors: HttpInterceptor[]
  ) {
    // interceptors is array of all registered interceptors
  }
}

Optional and Self Decorators

@Optional - Allow Missing Dependencies

import { Optional } from '@angular/core';

@Injectable()
export class MyService {
  constructor(
    @Optional() private logger?: Logger
  ) {
    // logger might be undefined
    this.logger?.log('Service created');
  }
}

@Self - Only Current Injector

import { Self } from '@angular/core';

@Component({
  selector: 'app-my-component',
  providers: [LocalService]
})
export class MyComponent {
  constructor(
    @Self() private local: LocalService // Only from this component
  ) {}
}

@SkipSelf - Skip Current Injector

import { SkipSelf } from '@angular/core';

@Component({
  selector: 'app-child',
  providers: [SharedService]
})
export class ChildComponent {
  constructor(
    @SkipSelf() private parent: SharedService // From parent, not self
  ) {}
}

@Host - Host Element Injector

import { Host } from '@angular/core';

@Directive({
  selector: '[appChild]'
})
export class ChildDirective {
  constructor(
    @Host() private parent: ParentComponent // From host component
  ) {}
}

ForRoot and ForChild Patterns

import { NgModule, ModuleWithProviders } from '@angular/core';

@NgModule({})
export class SharedModule {
  // For root module - configures services
  static forRoot(config: SharedConfig): ModuleWithProviders<SharedModule> {
    return {
      ngModule: SharedModule,
      providers: [
        SharedService,
        {
          provide: SHARED_CONFIG,
          useValue: config
        }
      ]
    };
  }

  // For feature modules - no service providers
  static forChild(): ModuleWithProviders<SharedModule> {
    return {
      ngModule: SharedModule,
      providers: [] // No providers, use root services
    };
  }
}

// Usage in AppModule
@NgModule({
  imports: [
    SharedModule.forRoot({ apiUrl: 'https://api.example.com' })
  ]
})
export class AppModule {}

// Usage in feature module
@NgModule({
  imports: [
    SharedModule.forChild()
  ]
})
export class FeatureModule {}

Tree-Shakable Providers

// Traditional (not tree-shakable)
@Injectable()
export class OldService {}

@NgModule({
  providers: [OldService]
})
export class AppModule {}

// Tree-shakable (preferred)
@Injectable({
  providedIn: 'root'
})
export class NewService {}

// No need to register in module
// Service is removed if never injected

Testing with DI

TestBed Provider Overrides

import { TestBed } from '@angular/core/testing';

describe('MyComponent', () => {
  let mockUserService: jasmine.SpyObj<UserService>;

  beforeEach(() => {
    mockUserService = jasmine.createSpyObj('UserService', ['getUsers']);

    TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        { provide: UserService, useValue: mockUserService }
      ]
    });
  });

  it('should get users', () => {
    mockUserService.getUsers.and.returnValue([]);
    const fixture = TestBed.createComponent(MyComponent);
    // Test component with mock
  });
});

Spy on Dependencies

import { TestBed } from '@angular/core/testing';

describe('UserService', () => {
  let service: UserService;
  let httpMock: jasmine.SpyObj<HttpClient>;

  beforeEach(() => {
    httpMock = jasmine.createSpyObj('HttpClient', ['get', 'post']);

    TestBed.configureTestingModule({
      providers: [
        UserService,
        { provide: HttpClient, useValue: httpMock }
      ]
    });

    service = TestBed.inject(UserService);
  });

  it('should fetch users', () => {
    httpMock.get.and.returnValue(of([]));
    service.getUsers().subscribe();
    expect(httpMock.get).toHaveBeenCalled();
  });
});

When to Use This Skill

Use angular-dependency-injection when building modern, production-ready applications that require:

  • Modular service architecture
  • Testable components and services
  • Configuration management
  • Plugin/extension systems
  • Multi-provider patterns (interceptors, validators)
  • Complex service hierarchies
  • Lazy-loaded module isolation
  • Tree-shakable code

Angular DI Best Practices

  1. Use providedIn: 'root' - Tree-shakable and singleton
  2. Use InjectionToken - Type-safe over string tokens
  3. Favor composition - Inject small, focused services
  4. Use factories for complex creation - useFactory for dynamic values
  5. Test with mocks - Override providers in TestBed
  6. Follow forRoot/forChild pattern - For shared modules
  7. Use @Optional sparingly - Prefer defaults or required deps
  8. Document multi-providers - Clear contract for extensions
  9. Avoid circular dependencies - Refactor to common service
  10. Use providedIn module - For module-specific services

DI Pitfalls and Gotchas

  1. Circular dependencies - A depends on B, B depends on A
  2. Providing in component - Creates new instance per component
  3. Missing providers - Runtime error if not provided
  4. Wrong injector level - Service not found in hierarchy
  5. Forgetting multi: true - Overrides instead of adding
  6. String token collisions - Use InjectionToken instead
  7. Not using forRoot - Multiple service instances
  8. Providing eagerly - Use providedIn for tree-shaking
  9. Testing without mocks - Real dependencies in tests
  10. Complex factory deps - Hard to test and maintain

Advanced DI Patterns

Service with Configuration

import { Injectable, Inject, InjectionToken } from '@angular/core';

export interface ApiConfig {
  baseUrl: string;
  timeout: number;
}

export const API_CONFIG = new InjectionToken<ApiConfig>('api.config');

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  constructor(@Inject(API_CONFIG) private config: ApiConfig) {}

  get(endpoint: string) {
    return fetch(`${this.config.baseUrl}/${endpoint}`, {
      signal: AbortSignal.timeout(this.config.timeout)
    });
  }
}

// Module
@NgModule({
  providers: [
    {
      provide: API_CONFIG,
      useValue: {
        baseUrl: 'https://api.example.com',
        timeout: 5000
      }
    }
  ]
})
export class AppModule {}

Abstract Class Provider

import { Injectable } from '@angular/core';

// Abstract class
export abstract class DataService<T> {
  abstract get(id: string): Observable<T>;
  abstract save(item: T): Observable<T>;
}

// Implementation
@Injectable()
export class UserDataService implements DataService<User> {
  get(id: string): Observable<User> {
    // Implementation
  }

  save(user: User): Observable<User> {
    // Implementation
  }
}

// Provider
@NgModule({
  providers: [
    { provide: DataService, useClass: UserDataService }
  ]
})
export class FeatureModule {}

// Usage
export class MyComponent {
  constructor(private dataService: DataService<User>) {}
}

Conditional Provider

import { Injectable, InjectionToken } from '@angular/core';
import { environment } from './environments/environment';

@Injectable()
export class DevLogger {
  log(message: string) {
    console.log('[DEV]', message);
  }
}

@Injectable()
export class ProdLogger {
  log(message: string) {
    // Send to logging service
  }
}

// Factory chooses implementation
export function loggerFactory(): Logger {
  return environment.production
    ? new ProdLogger()
    : new DevLogger();
}

const loggerProvider: Provider = {
  provide: Logger,
  useFactory: loggerFactory
};

Scope Isolation

// Parent service
@Injectable({
  providedIn: 'root'
})
export class GlobalState {
  count = 0;
}

// Child service (isolated)
@Injectable()
export class LocalState {
  count = 0; // Independent per component
}

@Component({
  selector: 'app-counter',
  providers: [LocalState] // New instance per component
})
export class CounterComponent {
  constructor(
    public global: GlobalState,
    public local: LocalState
  ) {}

  incrementGlobal() {
    this.global.count++; // Affects all components
  }

  incrementLocal() {
    this.local.count++; // Only this component
  }
}

Resources

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

OpenCode

28.43%
按下载量换算76

Cursor

25.29%
按下载量换算68

Codex

17.67%
按下载量换算48

Claude Code

13.41%
按下载量换算36

Gemini CLI

8.04%
按下载量换算22

windsurf

4.09%
按下载量换算11

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills