给出一个项目列表(将其视为多条消息的聊天),我希望使用moment.js来显示每个项目的相对时间(例如,自创建以来)。
每个项目都有自己的组件,使用以下代码显示相对时间:
get timeFromNow(): string {
return moment(this.pageLoaded).fromNow(); // pageLoaded is a JS Date
}问题是组件不会更新相对时间的显示,因为原始输入(在上面的示例中是pageLoaded)不会改变。
我的问题是:是否有处理这种情况的最佳做法?目前,我正在使用markForCheck of ChangeDetectorRef来触发重呈现。然而,我不确定这是否是一个好的方法性能。
我创建了一个简单的Stackblitz演示。在演示中,我使用前面提到的markForCheck来触发更新。
发布于 2018-07-01 12:02:59
从技术角度看,您有一个很好的解决方案。如果您想要更好的设计,那么就进入反应性编程的世界。
与手动启动检查不同,您可以使用流并让角执行以下工作:
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:它每1000 It发出一个值。然后我们用一个时间字符串替换这个值。就这样。每秒钟都会发出一个新的时间字符串。我添加了distinctUntilChanged(),这样只有当新值与旧值不同时才会发出新值。
在模板中,可以使用async管道使用流:
template: `Page loaded: <span class="relativeTime">{{ timeFromNow | async}}</span>`当发出新的时间字符串时,HTML将被更新。没有不必要的检查和计算。另外,通过使用async管道,当组件被销毁时,计时器会自动取消,并且您不会创建内存泄漏。
你可以检查一下分叉演示。
发布于 2019-02-13 14:50:30
更好的解决方案是使用timer(0, 1000)而不是interval(1000)。这将立即开火,然后每一秒。
请参阅http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-timer
https://stackoverflow.com/questions/51121577
复制相似问题