2015-12-30 70 views
3

我采用了棱角分明的一次性自定义指令结合基于特定属性(relative一次性绑定到自定义属性的指令

这是我的指令:

app.directive('relative', ['$timeout', '$filter', '$compile', function ($timeout, $filter, $compile) { 
    var dateFilter = $filter('date'); 

    return { 
     restrict: 'A', 
     scope: { 
      datetime: '@' 
     }, 
     link: function ($scope, $element, $attributes) { 
      var timeout; 

      $scope.$watch('datetime', function (dateString) { 
       $timeout.cancel(timeout); 

       var date = (dateString || $element.text()) * 1000; 
       if (!date) return; 
       date = new Date(date); 
       if (!date) return; 

       function update() { 
        var reference = new Date(); 
        $element.text(prettyDate(date)); 

        //Calculate the next update 
        var diff = Math.abs(date - reference)/1000; 
        var delta; 
        if (diff < 45) { 
         delta = 45 - diff; 
        } else if (diff < 90) { 
         delta = 90 - diff; 
        } else if (diff < 45 * 60) { 
         delta = 60 - (diff + 30e3) % 60; 
        } else { 
         delta = 3660 - diff % 3600; 
        } 

        timeout = $timeout(update, delta * 1000); 
       } 

       update();  

       $element.on('$destroy', function() { 
        $timeout.cancel(timeout); 
       }); 
      }); 
     } 
    }; 
}]); 

这是我如何使用它:

<time relative datetime="{{ notice.date }}"></time> 

或者:

<time relative datetime="{{ ::notice.date }}"></time> 

问题是:如何避免在使用一次性绑定时为datetime属性创建手表,因为该值永远不会更改?角是否自动执行?

+0

您自己创建一个观察器,并且可以在绑定该值后自行将其删除,以防一次性绑定。 'datetime:'@''是毫无意义的,如果你有你自己的观察者。 – zeroflagL

回答

0

我认为this是您正在寻找的解决方案。

您可以通过属性选取日期时间值,而不是通过您的范围对象接受它。这将避免创建不需要的手表。无论如何,你不希望这个价值得到改变,所以它不会有太大的影响。

+1

但是我并不总是使用该属性的一次性绑定,我只是在该值没有改变时显示特殊情况。我编辑了这个问题来澄清这一点。 –

0

我相信你最初使用$watch来触发update函数。您应该避免使用观察器,并选择重构观察器外部的初始化。为了避免初始触发角时,增加了一个观察的变量到监视列表,你可以做到这一点(source):

$scope.$watch('datetime', function (dateString, oldDateString) { 
    // notice the use of strict equality operator '===' 
    // angular ensures this will only be true on the initialization of the watcher 
    if (dateString === oldDateString) { 
     return; 
    } 
}); 

通过使用<time relative datetime="{{ ::notice.date }}"></time>角度不会触发后的一次性绑定观察者。

Scope对象上检查$$watchers属性之后,也看不出对具有或不具有$watch注册观察者的数量,这是我怀疑batarang使用任何差异。

为了回应您的问题,我相信不可能避免使用一次性绑定来创建观察者。

+0

但是像角度batarang这样的工具显示有一个手表活动,即使由于一次绑定而未触发。 –

+0

一旦你声明了一个观察者,角将它添加到观察者。解决这个问题的笨重方法是添加另一个属性并检查它是否存在,然后添加观察器。 – Boris

+0

@JavierMarín在检查我看到你可能因为从父项到子范围的绑定而得到观察者后,即'scope:{datetime:'@'}''这样batarang可能会向你展示你不期望的东西。我会编辑我的回复,说你不能停止观察者的初始化。 – Boris