mcpField
A
angular-directives

angular-directives

github.com/oguzhan18开发7176 次安装31 周前更新
代码仓库

关于 angular-directives

面向 Angular 21 指令开发与维护的参考技能,说明指令模式、近期 API 变化,以及构建专注且可复用行为的实践。

主要功能

  1. 01属性与结构型指令模式
  2. 02使用 hostDirectives 组合指令
  3. 03信号输入与独立指令
  4. 04TemplateRef 和 ViewContainerRef 用法
  5. 05保持指令专注并使用清晰选择器

适用场景

  1. 01创建可复用的元素行为
  2. 02构建条件嵌入视图
  3. 03在组件上组合多个指令
  4. 04为指令添加响应式输入

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/oguzhan18/angular-ecosystem-skills --skill angular-directives

安装后在 Claude Code 中输入/angular-directives确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/discussions/
_INDEX.md
references/docs/
_INDEX.md
references/issues/
_INDEX.md
references/releases/
_INDEX.md

详细介绍

Angular 指令

版本: Angular 21(2025) 标签: 指令、组件、DOM、自定义指令

参考: 指令指南 • 属性指令 • 结构型指令

API 变更

本节介绍近期特定版本的 API 变更。

  • 新增:指令组合 API — 使用 hostDirectives 组合指令 来源

  • 新增:指令中的信号输入 — 使用 input() 实现响应式指令属性

  • 新增:独立指令 — 所有指令都可以是独立的

  • 新增:控制流语法 — @if、@for、@switch 替代 *ngIf、*ngFor

最佳实践

  • 创建属性指令,实现可复用的行为
import { Directive, ElementRef, Renderer2, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  @Input() set appHighlight(color: string) {
    this.renderer.setStyle(this.el.nativeElement, 'background-color', color || 'yellow');
  }

  constructor(private el: ElementRef, private renderer: Renderer2) {}
}
  • 使用 @Input 和 @Output 实现指令间通信
@Directive({
  selector: '[appClickTracker]'
})
export class ClickTrackerDirective {
  @Input() trackName = 'default';
  @Output() clicked = new EventEmitter<string>();

  @HostListener('click')
  onClick() {
    this.clicked.emit(this.trackName);
  }
}
  • 使用 TemplateRef 创建结构型指令
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appUnless]'
})
export class UnlessDirective {
  @Input() set appUnless(condition: boolean) {
    if (!condition) {
      this.vcRef.createEmbeddedView(this.templateRef);
    } else {
      this.vcRef.clear();
    }
  }

  constructor(
    private templateRef: TemplateRef<any>,
    private vcRef: ViewContainerRef
  ) {}
}
  • 使用 ViewContainerRef 实现复杂的结构逻辑
@Directive({ selector: '[appDynamic]' })
export class DynamicDirective {
  constructor(
    private vcr: ViewContainerRef,
    private templateRef: TemplateRef<any>
  ) {
    this.vcr.createEmbeddedView(this.templateRef);
  }
}
  • 使用 hostDirectives 实现组合
@Component({
  selector: 'app-card',
  standalone: true,
  imports: [HighlightDirective],
  hostDirectives: [
    {
      directive: HighlightDirective,
      inputs: ['appHighlight: highlight']
    }
  ],
  template: `<ng-content></ng-content>`
})
export class CardComponent {}
  • 对现代指令使用 standalone: true
@Directive({
  selector: '[appStandalone]',
  standalone: true
})
export class StandaloneDirective {}
  • 在指令中使用信号
@Directive({
  selector: '[appSignal]'
})
export class SignalDirective {
  value = input<string>('');
  
  ngOnInit() {
    console.log(this.value());
  }
}
  • 使用 @HostBinding 进行属性绑定
@Directive({
  selector: '[appDisable]'
})
export class DisableDirective {
  @Input() set disabled(value: boolean) {
    this.hostBinding.nativeElement.disabled = value;
  }
  
  constructor(private hostBinding: ElementRef) {}
}
  • 保持指令专注 — 只承担一项职责
// ✅ Good - focused directive
@Directive({ selector: '[appTooltip]' })

// ❌ Bad - too many responsibilities
@Directive({ selector: '[appTooltip][appTooltipMaxWidth][appTooltipTheme]' })
  • 使用描述性选择器
// ✅ Good
@Directive({ selector: '[appUserCard]' })

// ❌ Bad
@Directive({ selector: '[appUc]' })

评论

支持 Markdown