是否可以在不从 DOM 读取的情况下在 Angular 中读取元素的文本内容?

Posted

技术标签:

【中文标题】是否可以在不从 DOM 读取的情况下在 Angular 中读取元素的文本内容?【英文标题】:Can the text content of an element be read in Angular without reading from the DOM? 【发布时间】: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 链接 【参考方案1】:

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

    可以在编译时提取。

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

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

【讨论】:

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

以上是关于是否可以在不从 DOM 读取的情况下在 Angular 中读取元素的文本内容?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不从原始源重新索引的情况下更改 Solr 架构中指定的分析器?

如何在不使用用户设置的情况下在运行时读取/写入 app.config 设置?

如何在不使用数据集的情况下在 Matlab 上比较不同的面部图像?

是否可以在不安装 Python 的情况下在 Windows 上安装 Robot Framework?

是否可以在不使用类变量的情况下在运行时在实例上创建 pyqtSignals?

是否可以在不使用情节提要的情况下在 xib 文件中创建原型内容 UITableview?