Angular.js - 向指令发出周期性事件

时间:2015-05-13 12:23:06

标签: javascript angularjs javascript-events angularjs-directive angularjs-scope

我有一个指令,它将日期和时间翻译成更好的 - 人类阅读形式,例如"现在","一分钟前",..

我想定期更新,所以日期翻译为"现在"将在一分钟后更新..

如何解决这个问题的一种方法是在指令中设置$ interval,以便在60&000; 000ms之后不断更新,但是对于使用该指令的大数据日期的页面来说可能是瓶颈。

第二个想法是制作服务,它将向$ rootScope播放事件hearthbeat,指令将绑定侦听器并更新其时间。但这也意味着我会每隔N秒遍历应用程序中的所有范围广播事件..

所以问题..有没有办法,如何使角度(更纯粹的溶解更好)服务将事件只发射到一个指令?

类似的东西:

$directive("timeAgo").$emit("hearthbeat", new Date().getTime())

3 个答案:

答案 0 :(得分:1)

您可以尝试使用过滤器而不是指令。据我所知,AngularJS会更新每个$ digest圈子的过滤器。因此,您根本不需要使用计时器。但我不确定我是否理解过滤器是如何正常工作的。

至于服务,您可以尝试使用$rootScope.$broadcast方法代替$rootScope.$emit。文档说$emit向上发送事件,而$broadcast向下发送事件。因此,对于前一个事件,该事件只能在$rootScope上访问,并且不会传播给其子项。您可以在官方文档中找到有关这些方法的更多信息,例如in this question

我认为,也可以使用常规回调而不是事件。您可以尝试向服务添加类似addTickEvenListener的方法,并在每个计时器滴答上仅调用已注册的回调。我不确定,但是当指令销毁时删除事件监听器可能会有些问题。也许这个问题可以通过听取范围的$destroy事件来解决,就像解释here一样。

答案 1 :(得分:1)

您可以创建一个过度的包装器指令,而不是依赖于$rootScope,您将在所有要使用智能日期的范围内使用它,如此...

app.directive('smartDateMaster', SmartDateMasterDirective);
function SmartDateMasterDirective() {
  return {
    restrict: 'AE',
    scope: true,
    controller: 'SmartDateController'
  };
}

app.controller('SmartDateController', ['$interval', '$scope', SmartDateCntl]);
function SmartDateCntl($interval, $scope) {

  // one interval is set, and the event is broadcast from this scope
  $interval(function() {
    $scope.$broadcast('sdPulse', new Date());
  }, 10000); // 10 seconds, adjust to taste

}

...然后在您想要显示其中一个智能相对日期的任何地方,使用监听事件并相应更新的指令:

app.directive('smartDate', SmartDateDirective);
function SmartDateDirective() {
  return {
    restrict: 'A',
    template: '<span>{{ dateText }}</span>',
    scope: {
      srcDate: '=smartDate' /* a reference to a JS time object */
    },
    link: function($scope, elem, attrs) {

      $scope.$on('sdPulse', function(evt, currentDate) {
        var difference = currentDate.getTime() - $scope.srcDate.getTime();

        // some logic to determine what the date text should be based on difference

        // then set it in scope for display
        $scope.dateText = 'whatever you decided';
      });
    }
  };
}

HTML中的实现看起来像这样,您可以使用Smart Date Master指令包装所有出现的智能日期。在您想要智能日期的任何地方,使用smart-date属性以及指向父作用域中日期的可指定表达式。

<body>

  <!-- some outer content unconcerned with dates -->

  <smart-date-master>

    <!-- some inner content with dates spread throughout -->

    <div>
      Jack commented on your status <span smart-date="jackCommentDate"></span>.
    </div>

    <div>
      Jill poked you <span smart-date="jillPokeDate"></span>.
    </div>

    <div>
      John sent you a message <span smart-date="johnMsgDate"></span>
    </div>

  </smart-date-master>

</body>

这应该仍然是一个高效的解决方案,你不会做任何非标准或非常低效的事情。

答案 2 :(得分:0)

我创建了一个解释一些粗略想法的plunker:     http://plnkr.co/edit/d8vE0HCLbemgiPNuvl47?p=preview

It is not complete yet since elements are not moved to different queues after         threshold is met.