Angular Directives观看外部模型

时间:2014-02-13 20:08:46

标签: javascript angularjs angularjs-directive

在学习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的小提琴。

2 个答案:

答案 0 :(得分: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 fiddlehttp://jsfiddle.net/dv7fy/1/

作为旁注,Angular手表的性能比大多数人想象的要好,看一下这个例子(仍然在Angular 1.0.3上,在最新版本上应该更好):http://jsfiddle.net/mhevery/cXMPJ/11/

答案 1 :(得分: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指令是可见的。 (请参阅小提琴中的两个“注释”注释。)