【问题标题】:How to check if another directive is present on the same element如何检查同一元素上是否存在另一个指令
【发布时间】:2025-12-04 13:05:02
【问题描述】:

假设我有两个指令:

@Directive({
  selector: '[appDirective1]'
})
export class Directive1Directive {

  public alone = true;

  constructor(private element: ElementRef<HTMLInputElement>) { }

  ngOnInit() {
    if (this.alone) {
      this.element.nativeElement.innerHTML = "I am alone";
    } else {
      this.element.nativeElement.innerHTML = "I have a friend";
    }
  }
}

@Directive({
  selector: '[appDirective2]'
})
export class Directive2Directive {

  constructor() { }

}

如果Directive2 出现在同一元素上,我希望Directive1 改变其行为。例如,它们应该有不同的行为。

<div appDirective1></div>
<div appDirective1 appDirective2></div>

我是否可以在不添加服务以促进通信的情况下执行此操作*?

StackBlitz 示例:https://stackblitz.com/edit/angular-bgqd15


*我想避免为此创建新服务,因为这感觉有点矫枉过正。

【问题讨论】:

    标签: angular angular2-directives angular-directive


    【解决方案1】:

    我认为Reactgular's answer 更好,因为它可以根据需要轻松应用于任一指令。


    根据这两个指令的关系,我找到了以下解决方案:

    Directive1 明确检查Directive2

    @Directive({
      selector: '[appDirective1]'
    })
    export class Directive1Directive {
    
      public alone = true;
    
      @Input("appDirective2")
      public appDirective2: any;
    
      constructor(private element: ElementRef<HTMLInputElement>) { }
    
      ngOnInit() {
        if (this.appDirective2 !== undefined) {
          this.alone = false;
        }
        if (this.alone) {
          this.element.nativeElement.innerHTML = "I am alone";
        } else {
          this.element.nativeElement.innerHTML = "I have a friend";
        }
      }
    }
    

    StackBlitz 示例:https://stackblitz.com/edit/angular-5w63vu

    Directive2提供一个钩子告诉Directive1

    @Directive({
      selector: '[appDirective1]'
    })
    export class Directive1Directive {
    
      public alone = true;
    
      constructor(private element: ElementRef<HTMLInputElement>) { }
    
      ngOnInit() {
        this.setContent();
      }
    
      setFriend() {
        this.alone = false;
        this.setContent();
      }
    
      setContent() {
        if (this.alone) {
          this.element.nativeElement.innerHTML = "I am alone";
        } else {
          this.element.nativeElement.innerHTML = "I have a friend";
        }
      }
    }
    
    @Directive({
      selector: '[appDirective2]'
    })
    export class Directive2Directive {
    
      constructor(@Self() private otherDirective: Directive1Directive ) { }
    
      ngOnInit() {
        this.otherDirective.setFriend();
      }
    }
    

    StackBlitz 示例:https://stackblitz.com/edit/angular-bag8wa

    【讨论】:

      【解决方案2】:

      您可以使用Host() 装饰器通过构造函数注入相邻指令,也可以将其设为Optional()

        constructor(@Optional() @Host() public friend: Directive2Directive) { }
      
        ngOnInit() {
          if (this.friend) {
            this.element.nativeElement.innerHTML = "I have a friend";
          } else {
            this.element.nativeElement.innerHTML = "I am alone";
          }
        }
      

      组件、指令和提供程序是可注入的,您可以将 DI 限制为仅在当前 主机 级别上搜索。

      【讨论】:

      • 您是否更喜欢@Host 而不是@Self (angular.io/api/core/Self)?我对其中的区别不是很熟悉,但我最初的印象是@Host 会撒下更大的网
      • @Vlad274 @Self() 从当前主机开始向上走直到找到提供者。 @Host() 只查看当前主机,如果没有找到就停止。
      • 哇,@Self 实际上是更广泛的网络!感谢您的信息!
      • @Vlad274 我感觉@Self()是默认的,因为我们也有@SkipSelf()所以不使用@Self()有什么区别呢?所以这就是为什么我认为这是默认设置,但我检查了文档并无法在那里确认。
      最近更新 更多