指令链接函数中的$ timeout

时间:2017-04-03 08:54:39

标签: css angularjs ionic-framework

因此,我使用此指令折叠Ionic中的可变高度卡。该指令获取自动高度并将其更改为定义的高度,然后可以使用css动画将其折叠为0。它可以满足我的需求,但现在我需要使用ng-src动态加载卡片中的图像。发生的是在指令后正在加载图像,因此图像会加载并溢出卡片。

指令:

.directive('collapse', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',

        link: function ($scope, ngElement, attributes) {
            var element = ngElement[0];


            $timeout(function(){                
                $scope.$watch(attributes.collapse, function (collapse) {
                            var newHeight = collapse ? 0 : getElementAutoHeight();

                            element.style.height = newHeight +"px";
                            ngElement.toggleClass('collapsed', collapse);
                        });

            function getElementAutoHeight() {
                var currentHeight = getElementCurrentHeight();

                element.style.height = 'auto';
                var autoHeight = getElementCurrentHeight();

                element.style.height = currentHeight +"px";
                getElementCurrentHeight(); // Force the browser to recalc height after moving it back to normal

                return autoHeight;
            }

            function getElementCurrentHeight() {
                return element.offsetHeight
            }
         });
      }
    };
}])

和HTML:

<div ng-repeat="item in items | orderBy : '-'" collapse="item.deleted">
    <div class="list card">
        <img class="full-image" ng-src="{{item.image}}"/>
    </div>
</div>

正如你所看到的那样,我注入$timeout并将间隔留空,希望它会等到DOM加载,但似乎无论我如何使用它,该指令仍明确设置渲染image子元素之前css中元素的高度。如何在每个ng-src项目中加载ng-repeat之前延迟元素高度的设置?

2 个答案:

答案 0 :(得分:1)

首先,没有$ interval的angular $ timeout 不会等待DOM树加载,基本上,它所做的是等待当前摘要周期到在第一个参数中执行函数之前完成。通过这样做,它将允许您的代码在计算div的高度之前等到指令完成编译和渲染。

但是,无法保证此时将加载图像。浏览器独立于DOM渲染加载图像,因此,要精确计算具有图像的容器的高度,您应该使用 JS Image Object 加载事件 。图像完全加载后,您可以更新高度。

另外,对于你的指令,我不认为你需要每次折叠变量改变时计算高度(在手表内),你可以等到图像被加载,计算高度一次,存储它位于范围对象内部,并在崩溃变量发生变化时重复使用它。

答案 1 :(得分:0)

好的,感谢泰国人的投入,我有一个有效的解决方案:

.directive('collapse', [function () {
    return {
        restrict: 'A',

        link: function ($scope, ngElement, attributes) {
            var element = ngElement[0];

            var img = element.querySelector('.full-image');

            angular.element(img).bind('load', function() {

               var autoHeight = getElementAutoHeight();

               element.style.height = autoHeight + "px";


            }); 

            $scope.$watch(attributes.collapse, function (collapse) {
                var newHeight = collapse ? 0 : getElementAutoHeight();

                element.style.height = newHeight +"px";
                ngElement.toggleClass('collapsed', collapse);
            });

            function getElementAutoHeight() {
                var currentHeight = getElementCurrentHeight();

                element.style.height = 'auto';
                var autoHeight = getElementCurrentHeight();

                element.style.height = currentHeight +"px";
                getElementCurrentHeight(); // Force the browser to recalc height after moving it back to normal

                return autoHeight;
            }

            function getElementCurrentHeight() {
                return element.offsetHeight
            }
        }
    };
}])