Javascript 绑定数据后从指令操纵DOM

Javascript 绑定数据后从指令操纵DOM,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我的目标是创建一个指令,将一组不同高度的div排列成一个模式,以消除它们之间的空白。如Pinterest细分细分细分为马赛克: 我的做法是: 创建一个指令,该指令将包装一组要细分的div <tessellate columns="6"> <div ng-repeat="item in items" class="thumbnail"> {{item.name}} </div> </tessellate> 看起来

我的目标是创建一个指令,将一组不同高度的div排列成一个模式,以消除它们之间的空白。如Pinterest细分细分细分为马赛克:

我的做法是:

  • 创建一个指令,该指令将包装一组要细分的div

    <tessellate columns="6">
        <div ng-repeat="item in items" class="thumbnail">
            {{item.name}}
        </div>
    </tessellate>
    
  • 看起来很简单,对吧?我经常遇到的问题是,在数据绑定到div之后,我无法找出如何获取div。这一点很重要,因为需要div的实际高度来决定它应该放在哪个列中


    数据绑定后,是否有方法在指令中操作DOM?

    要回答我自己的问题,我唯一能弄明白这一点的方法是使用$timeout。我不喜欢它,但它很管用。如果有人有更好的方法,请发布答案。:)

    我修改了我的指令模板(tessellateTemplate.html)以转移div:

    <div>
        <div class="container">
            <div class="row">
                <div class="col-sm-{{12/columns}}" ng-repeat="i in numberToArray(columns) track by $index"></div>
            </div>
        </div>
        <div ng-transclude></div>
    </div>
    
    用法保持不变:

    <tessellate columns="6">
        <div ng-repeat="item in items">
            {{item.name}}
        </div>
    </tessellate>
    
    
    {{item.name}
    
    您在div上尝试过ng init吗?没有,我从未使用过ng init。我必须研究一下,用这个来代替表达式,你也可以传递函数,并在作用域中处理它,所以我猜我必须使用转置。等等,ng init,按设计,不是在ng重复之前运行吗?
    <div>
        <div class="container">
            <div class="row">
                <div class="col-sm-{{12/columns}}" ng-repeat="i in numberToArray(columns) track by $index"></div>
            </div>
        </div>
        <div ng-transclude></div>
    </div>
    
    app.directive('tessellate', function () {
        return {
            restrict: 'E',
            replace: true,
            transclude: true,
            scope: {
                columns: '='
            },
            controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
                // Ensure number of columns is divisible by 12.
                if (isNaN($scope.columns) || 12 % $scope.columns != 0) {
                    $scope.columns = 6;
                }
    
                $scope.numberToArray = function (num) {
                    return new Array(num);
                };
    
                $scope.getShortestColumn = function () {
                    var cols = $element.children().first().children().first().children();
                    var shortCol = null;
                    angular.forEach(cols, function (col) {
                        col = angular.element(col);
                        if (shortCol == null || col.height() < shortCol.height()) {
                            shortCol = col;
                        }
                    });
                    return shortCol;
                };
    
                $timeout(function () {
                    var divs = $element.children().first().next().children();
                    for (var i = 0; i < divs.length; i++) {
                        $scope.getShortestColumn().append(divs[i]);
                    }
                }, 0);
            }],
            templateUrl: "/app/directives/templates/tessellateTemplate.html"
        };
    });
    
    <tessellate columns="6">
        <div ng-repeat="item in items">
            {{item.name}}
        </div>
    </tessellate>