使用Moment.js自动更新相对时间的显示

时间:2018-07-01 08:19:06

标签: angular momentjs angular-changedetection

给出一个项目列表(将其视为与多条消息聊天),我想使用显示每个项目的相对时间(例如,自创建以来)。

每个项目都有其自己的组成部分,并且使用以下代码显示相对时间:

'<div class="w3-border w3-center">&nbsp;</div>'

问题在于该组件不会更新相对时间的显示,因为原始输入(上例中的get timeFromNow(): string { return moment(this.pageLoaded).fromNow(); // pageLoaded is a JS Date } )不会更改。

我的问题是:处理这种情况是否有最佳实践?目前,我正在使用pageLoaded中的markForCheck来触发重新渲染。但是,我不确定这是否是一种性能良好的方法。

我已经创建了一个简单的demo on Stackblitz。在演示中,我使用前面提到的ChangeDetectorRef触发更新。

2 个答案:

答案 0 :(得分:4)

从技术角度来看,您有一个好的解决方案。如果您想要更好的设计,请进入反应式编程的世界。

您可以使用流并让Angular完成工作,而不是手动开始检查:

export class MomentComponent implements OnInit  {
  pageLoaded: Moment;
  timeFromNow: Observable<string>;

  ngOnInit() {
    this.pageLoaded = moment(new Date());

    this.timeFromNow = interval(1000).pipe(
                         map(() => this.pageLoaded.fromNow()),
                         distinctUntilChanged()
                       );
  }
}
在您的示例中,

interval的工作方式类似于setInterval:每1000ms发出一个值。然后,我们用一个时间字符串替换该值。而已。每秒钟发出一个新的时间字符串。我添加了distinctUntilChanged(),以便仅在与旧值不同时才发出新值。

您可以在模板中使用async管道使用流:

template: `Page loaded: <span class="relativeTime">{{ timeFromNow | async}}</span>`

当发出新的时间字符串时,将更新HTML。没有不必要的检查和计算。作为奖励,使用async管道可以在组件销毁并且您不会造成内存泄漏时自动取消计时器。

您可以检查forked demo

答案 1 :(得分:2)

一个更好的解决方案是使用timer(0, 1000)而不是interval(1000)。这将立即触发,然后每秒触发一次。

请参见http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-timer