在Angularjs和Momentjs中更新“time ago”值

时间:2013-08-01 23:27:26

标签: angularjs momentjs

原文:我有一个用ng-repeat生成的表,有数百个条目,包含几个不同的unix时间戳。我正在使用moment.js让它们显示为“19分钟前”,或者很久以前就是这样。我如何每五分钟更新一次,例如,无需刷新整个表格(这需要几秒钟,并会中断用户的排序和选择)。

5 个答案:

答案 0 :(得分:16)

我使用以下过滤器。每60秒过滤一次更新值。

var text = g.append("text")  
  .style("font-size", 20)
  .append("textPath")
  .text(function(d, i) {
    return segments[i];
  })
  .attr("textLength", function(d, i) {
    return 90 - i * 5;
  })
  .attr("xlink:href", function(d, i) {
    return "#s" + i;
  })
  .attr("startOffset", function(d, i) {
    return segmentOffsets[i];
  })

并在html中

angular
  .module('myApp')
  .filter('timeAgo', ['$interval', function ($interval){
    // trigger digest every 60 seconds
    $interval(function (){}, 60000);

    function fromNowFilter(time){
      return moment(time).fromNow();
    }

    fromNowFilter.$stateful = true;
    return fromNowFilter;
  }]);

答案 1 :(得分:13)

我相信filters are evaluated every digest cycle,所以使用过滤器显示你的"之前的时间"数百个条目可能会使字符串变得昂贵。

我决定使用pubsub架构,使用基本上eburley's建议的方法(主要是因为我不必注意$destroy事件并手动取消订阅),但使用NotificationService而不是而不是"频道"功能:

.factory('NotificationService', ['$rootScope',
function($rootScope) {
    // events:
    var TIME_AGO_TICK = "e:timeAgo";
    var timeAgoTick = function() {
        $rootScope.$broadcast(TIME_AGO_TICK);
    }
    // every minute, publish/$broadcast a TIME_AGO_TICK event
    setInterval(function() {
       timeAgoTick();
       $rootScope.$apply();
    }, 1000 * 60);
    return {
        // publish
        timeAgoTick: timeAgoTick,
        // subscribe
        onTimeAgo: function($scope, handler) {
            $scope.$on(TIME_AGO_TICK, function() {
                handler();
            });
        }
    };
}])

time-ago指令使用NotificationService注册/订阅时间戳(下面的示例HTML中为post.dt):

<span time-ago="post.dt" class="time-ago"></span>

.directive('timeAgo', ['NotificationService',
function(NotificationService) {
    return {
        template: '<span>{{timeAgo}}</span>',
        replace: true,
        link: function(scope, element, attrs) {
            var updateTime = function() {
                scope.timeAgo = moment(scope.$eval(attrs.timeAgo)).fromNow();
            }
            NotificationService.onTimeAgo(scope, updateTime); // subscribe
            updateTime();
        }
    }
}])

一些评论:

  • 我试图提高效率,而不是让指令创建新的范围。虽然该指令在范围中添加了timeAgo属性,但在我的使用中,这是可以的,因为我似乎只在ng-repeat中使用time-ago指令,所以我只是添加由ng-repeat创建的子范围的属性。
  • 每个摘要周期都会检查
  • {{timeAgo}},但这应该比运行过滤器更快
  • 我也喜欢这种方法,因为我没有在每个时间戳上运行计时器。我在NotificationService中运行了一个计时器。
  • 函数timeAgoTick()可以设为私有,因为可能只有NotificationService需要发布time time事件。

答案 2 :(得分:4)

使用angular的$timeout服务(只是setTimeout()周围的包装)来更新您的数据。请注意第三个参数,它指示Angular应运行$digest周期,以更新数据绑定。

以下是一个例子:http://jsfiddle.net/jandersen/vfpDR/
(此示例每秒更新一次,因此您不必等待5分钟才能看到它; - )

答案 3 :(得分:0)

我最后通过setInterval每隔五分钟调用一次scope.apply(),它会重新应用将时间戳格式化为“x分钟前”的过滤器。也许有点hacky但它​​的确有效。我确定这不是最佳解决方案。

答案 4 :(得分:0)

我为momentjs https://github.com/jcamelis/angular-moment

制作了一个包装器
<p moment-interval="5000">{{"2014-05-21T14:25:00Z" | momentFromNow}}</p>

我希望它适合你。