【问题标题】:$timeout in a directive link function指令链接函数中的 $timeout
【发布时间】:2017-04-04 05:43:19
【问题描述】:

所以我使用这个指令来折叠 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 加载完毕,但似乎无论我如何使用它,该指令仍然显式设置元素的高度在呈现图像子元素之前的 css 中。如何将元素高度的设置延迟到每个 ng-repeat 项目中加载 ng-src 之后?

【问题讨论】:

  • 你在哪里使用 $timeout ?这是语法$timeout(function(){//yourcode}
  • 我试过把它包在手表上,把所有东西都包起来,等等。没有一个工作。我已经编辑了原始帖子以反映其中一项尝试。
  • $watch 放入$timeout 只会延迟监视处理程序的注册,直到下一个摘要周期。这并不能保证 CSS 操作发生在图像加载之后。加载资源后,浏览器会在 &lt;img&gt; 元素上触发“加载”事件。使用该事件对 CSS 的更改进行排序。

标签: css angularjs ionic-framework


【解决方案1】:

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

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

另外,对于您的指令,我认为您不需要每次折叠变量更改时都计算高度(在手表内),您可以简单地等到加载图像,计算一次高度,并将其存储在里面范围对象,并在折叠变量更改时重用它。

【讨论】:

    【解决方案2】:

    好的,感谢 Thai 的意见,我有一个可行的解决方案:

    .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
                }
            }
        };
    }])
    

    【讨论】:

      猜你喜欢
      • 2014-03-11
      • 1970-01-01
      • 2014-07-05
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-28
      相关资源
      最近更新 更多