【问题标题】:Can the text content of an element be read in Angular without reading from the DOM?是否可以在不从 DOM 读取的情况下在 Angular 中读取元素的文本内容?
【发布时间】:2018-06-02 09:49:58
【问题描述】:

我需要能够在我的 Angular 应用程序的代码中使用翻译后的字符串,但由于 i18n 工具还不能胜任这项任务,我实现了一个稍微有点 hacky 的版本,它利用了 Angular 现有的 i18n 功能,目的是逐步淘汰我的原生 Angular 解决方案,因为它的 i18n 功能可以满足我的需求(应该是 5.x release,手指交叉)。

基本上,我有一个 TranslationDirective 从 DOM 读取文本,并在文本更改时发出事件:

@Directive({
  selector: '[myAppTranslation]'
})
export class TranslationDirective implements AfterViewChecked, OnChanges {
  /**
   * dependencies takes an array of the values needed to calculate the output translation
   * we use this for change detection, to minimize the DOM interaction to only when it is necessary
   */
  @Input() dependencies: any[];
  isDirty = true;
  @Input() messageKey: string;
  message: string;
  @Output() messageUpdated = new EventEmitter<TranslationEvent>();

  constructor(public el: ElementRef) {}

  /**
   * sets the translated message and triggers the TranslationEvent
   */
  setMessage() {
    const message = (this.el.nativeElement.textContent || '').trim();
    const oldMessage = (this.message || '');
    if (oldMessage !== message) {
      this.message = message;
      this.isDirty = false;
      this.triggerTranslationEvent();
    }
  }

  ngOnChanges() {
    this.isDirty = true;
  }

  ngAfterViewChecked() {
    if (this.isDirty) {
      this.setMessage();
    }
  }

  /**
   * triggers the messageUpdated EventEmitter with the TranslationEvent
   */
  triggerTranslationEvent() {
    // need to delay a tick so Angular doesn't throw an ExpressionChangedAfterItHasBeenCheckedError
    setTimeout(() => {
      const event = new TranslationEvent(this.messageKey, this.message);
      this.messageUpdated.emit(event);
    });
  }
}

export class TranslationEvent {
  constructor(public messageKey: string, public message: string) {}
}

这样使用:

<span
  myAppTranslation
  i18n
  [dependencies]="[today]"
  [messageKey]="todaysDateKey"
  (messageUpdated)="setTodaysDateTranslation($event)"
>
  Today is {{today | date:'short'}}
</span>

由于要翻译的字符串都驻留在模板中,Angular 的 xi18n 工具可以很好地读取它们,Angular 编译器会将它们替换为翻译后的字符串。

这是实用的,但不是很好。我怀疑有一个计时错误正等着咬我,但还没有表现出来。有一个效率低下且缓慢的写入到 DOM-从 DOM 读取的循环,如果消除这种循环非常好。

如果我能避免的话,我希望能够通过绕过 DOM 来消除一个问题来源。 Angular 是否会保留一个元素内容的内存副本,无需通过 DOM 即可访问?如果可以的话,我可以避免将翻译元素完全写入 DOM 吗?

【问题讨论】:

  • 使用 ngModel 怎么样?并请提供 plunker 链接

标签: angular internationalization angular-directive


【解决方案1】:

看起来您的很多复杂性是因为您想要支持动态文本 - 文本可能会在运行时更改。我认为您不需要这样做,因为 i18n 文本需要是静态的,以便:

  1. 可以在编译时提取。

  2. 可以提前翻译,所有翻译都存储在以后的编译时。

您的示例“今天是……”是不可翻译文本的完美示例。 :-) 您应该将其更改为仅将“今天是”本身作为文本块,然后将日期显示为当前区域设置超出该跨度。

【讨论】:

  • Angular 的 i18n 工具支持该格式的翻译。需求来自期望通过配置对象传递文本的第 3 方库,我需要翻译该文本。
  • 哇,我的错,我不知道 Angular i18n 工具可以处理这个问题。但是,您使用了 double-{},所以在调用 myAppTranslation 指令之前,不是让 Angular 动态评估表达式吗?
  • 是的,它将在指令被调用之前被评估——这是重点的一部分。示例用例包括需要本地化的日期。将日期附加到翻译的字符串不是一种选择,因为翻译可以在不同语言的字符串中移动日期的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-20
  • 2012-06-27
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多