1

我正在实现一个指令,它将一种语言(或一组语言)作为输入,并将一个类添加到添加指令的 DOM 元素中。

@Directive({
  selector: '[appRtlView]'
})
export class RTLViewDirective implements OnInit, OnChanges {
  @Input('appRtlView') inputLanguage: string | string[];

  constructor(private el: ElementRef) {}

  ngOnInit() {
    this.handleRtl();
  }

  private handleRtl() {
    if (this.inputLanguage) {
      let languageList = null;

      if (!Array.isArray(this.inputLanguage)) {
        languageList = [this.inputLanguage];
      } else {
        languageList = this.inputLanguage;
      }

      // both conditions do stuff with this.el.nativeElement.classList
      if (languageList.includes('ar')) {
        this.addRtl();
      } else {
        this.removeIfRtlExists();
      }
    }
  }
}

下面是我使用该指令的地方。"languagesInView" 是一个字符串列表,在使用该指令的组件中使用 @Input() ...

<div *ngIf="concept">
  <div class="concept-header" [appRtlView]="languagesInView">
    ...
  </div>
</div>

我希望当传递给组件的languagesInView 输入发生变化时,我在模板中传递给[appRtlView] 的值会发生变化。(我可以通过使用插值{{languagesInView }}将值打印到屏幕来看到值实际上发生了变化)

在 RTLView 指令中,如果我使用 ngOnInit,则不会拾取对“inputLanguage”字段的更改。

为了克服这个问题,我在指令中使用了 ngOnChanges(实现 OnChanges 可以满足我的要求):

// ngOnInit added because Angular doesn't accept a directive without an OnInit implementation
  ngOnInit() {}

  ngOnChanges(change: SimpleChanges) {
    // TODO: A check to see if the input value has changed or not would help performance
    this.handleRtl();
  }

我无法将 changeDetectionStrategy 添加到指令初始化中,这让我认为指令通常不应该实现 OnChanges。我的在线搜索并没有太大帮助。

在 Angular 指令中运行 ngOnChanges 是错误的吗?

谢谢

4

2 回答 2

0

ngOnChanges仅当输入更改来自模板绑定(如<component [someInput]="aValue">.

有几种方法可以解决这个问题。

  • 直接做出ngOnChanges会做的改变。
  • 使用 手动触发更改检测ChangeDetectorRef
于 2019-03-12T09:19:24.977 回答
0

我想我有我的答案,来自生命周期钩子文档。我的问题归结为我是否可以在指令中使用/应该使用 ngOnChanges。粗体线几乎是我所需要的。

生命周期挂钩

组件的生命周期由 Angular 管理。

Angular 创建它,渲染它,创建和渲染它的子节点,当它的数据绑定属性发生变化时检查它,并在从 DOM 中删除它之前销毁它。

Angular 提供了生命周期钩子,可以提供对这些关键生命时刻的可见性以及在它们发生时采取行动的能力。

指令具有相同的生命周期钩子集。

感谢大家的回应。

于 2019-03-12T09:37:22.667 回答