2015-12-30 69 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