2014-02-13 47 views
7

在學習Angular中,我創建了一個可以放大的簡單畫廊。我最初的實現使用了一個簡單的ng-repeat,但我很快發現,基於畫廊的縮放,我想要改變諸如url源(從小到中等大小)以及可能在字幕上的css等。觀看外部模型的角度指令

<div class="photoHolder" ng-repeat="photo in photos | filter:{caption:query} | orderBy:orderProp" ng-attr-style="transition: .3s ease; width: {{thumbWidth}}px; height: {{thumbWidth}}px;"> 
    <div class="photoClass" data-id="{{photo.id}}" ng-attr-style="background-image:url({{zoomSize < 5 ? photo.thumb_url : photo.medium_url}})"></div> 
    <div class="caption">{{photo.caption}}</div> 
    <div class="caption">{{photo.date}}</div> 
</div> 

所以,我切換到更清潔的指令:

<gal-photo class="photoHolder" ng-repeat="photo in photos | filter:{caption:query} | orderBy:orderProp"/> 

,但我能得到指令元素變焦變化做出反應的唯一方法是手錶添加到變焦的鏈接內元素:

link: function(scope, element, attrs) { 
    var image = new Image(); 
    scope.photo.url = scope.zoomSize < 5 ? scope.photo.thumb_url : scope.photo.medium_url; 
    scope.$watch('thumbWidth', function() { 
      scope.photo.url = scope.zoomSize < 5 ? scope.photo.thumb_url : scope.photo.medium_url; 
     element.attr('style', 'transition: .3s; width: ' + scope.thumbWidth + 'px; height: ' + scope.thumbWidth + 'px;'); 
    }); 
} 

我知道你不應該濫用手錶,而我的恐懼是,在畫廊中有500個元素,你正在做500個手錶。但是在重複指令中,我無法找到有關對外部輸入做出響應的指導。兩個畫廊似乎表現相同,但我想知道我是否做錯了?這裏是original gallery的小提琴和directive version的小提琴。

+0

我喜歡用ng-attr樣式的原始解決方案,因爲它的代碼較少,但聽起來這更像是一個性能問題。我會檢查出這樣的問題 - > http://stackoverflow.com/questions/20702140/improving-nested-ng-repeat-directive-performance – koolunix

+0

是的,我已經檢查出來......我正在尋找指導人們在模型中處理外部輸入的方式。就像我說的那樣,表現並沒有明顯的不同。我更喜歡這個指令,因爲它不是HTML,看起來更強大,我只是想知道我是否做錯了。 –

+0

這也是一個非常好的:http://stackoverflow.com/questions/9682092/databinding-in-angularjs/9693933#9693933 – koolunix

回答

3

我認爲Beyers是正確的,手錶實際上是非常有效的。

不過,這裏是你如何能與手錶做到這一點通過使用父指示整個圖片庫:

myApp.directive('imageGallery', function() { 
return { 
    restrict: 'A', 
    controller: function($scope, $element, $attrs) { 
     function updatePhotos() { 
      $element.children().attr('style', 'transition: .3s; width: ' + $scope.thumbWidth + 'px; height: ' + $scope.thumbWidth + 'px;'); 
      $scope.photos.forEach(function(photo){ 
       photo.url = $scope.zoomSize < 5 ? photo.thumb_url : photo.medium_url; 
      }); 
     }; 

     this.updatePhotos = updatePhotos; 
    }, 
    link: function(scope, element, attrs, ctrl) { 
     scope.$watch('thumbWidth', function() { 
      ctrl.updatePhotos(); 
     }); 
     ctrl.updatePhotos(); 
    } 
} 
}); 

(full fiddle here)

請注意,我已經把中央更新邏輯轉換爲controller而不是link函數。這在這裏不是必須的,但將來可能會有用,因爲該控制器對象對於子代galPhoto指令是可見的。 (請參閱小提琴中的兩條「NOTE」註釋。)

+0

聖牛,是光滑的相比,其他版本。 (Beyers和我的原創)。 –

+1

嘿,謝謝。不過值得注意的是,由於galPhoto指令的每個實例通過{{}}插值引用其「照片」對象,因此此解決方案中的手錶數量基本上與照片數量成正比......他們而不是在你的代碼中。 – anandthakker

6

您的用例是$ scope事件的良好候選者。有一個表控制器內:

$scope.$watch('thumbWidth', function() { 
    $scope.$broadcast('thumbWidthChange'); 
}); 

,然後在指令寄存器聽衆此事件:當他們的事件被觸發

scope.$on('thumbWidthChange', function(){ 
    scope.photo.url = scope.zoomSize < 5 ? scope.photo.thumb_url : scope.photo.medium_url; 
    element.attr('style', 'transition: .3s; width: ' + scope.thumbWidth + 'px; height: ' + scope.thumbWidth + 'px;'); 
}); 

範圍的事件監聽器只被調用,所以這應該限制腕錶列出並優化性能。

這裏是一個updated fiddle基於使用事件的方法,你的例子:http://jsfiddle.net/dv7fy/1/

作爲一個側面說明,角手錶的性能擴展優於大多數想,看看下面這個例子(仍在角1.0。 3,在最新版本上應該更好):http://jsfiddle.net/mhevery/cXMPJ/11/