解决方案/想法集中统一调用功能

时间:2017-05-19 08:08:32

标签: javascript jquery html angularjs

所以这个有点难以解释,但我会尝试一下:

我有一个班级.boxes的div。它是一些循环元素的包装器。循环元素具有类.box。在这个元素中,还有两个元素。一个是类.box-header的标题,一个是类.box-content的内容。我可以点击它来打开和关闭这些元素,所以如果它已经关闭,我只看到.box-header,如果它已经打开,我也可以看到.box-content

以下是截图,其中显示了这种情况(灰色容器.boxes,其中元素.box处于关闭/打开的不同状态中): enter image description here

我有不同组件的列表,所以不止一次。结构大致相同。因此,示例模板如下所示:

<!--wrapper boxes-->
<div class="boxes">
    <!--looped element box-->
    <div class="box boxFor{{::box.id}}" ng-repeat="box in boxes" ng-class="{fill-container: boxes.length == 1}">
        <!--box header-->
        <div class="box-header" ng-click="box.open = !box.open">
            {{::box.name}}
        </div>
        <!--box content-->
        <div class="box-content" ng-if="box.open">
            <!--some content-->
        </div>
    </div>
</div>

以下是类的示例样式:

.boxes {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    overflow: auto;
    .box {
        display: flex;
        flex-direction: column;
        flex: 0 0 auto;
        margin-bottom: 5px;
    }
    .box-header {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        min-height: 30px;
        line-height: 20px;
        font-size: 16px;
        padding: 5px;
    }
    .box-content{
        padding: 5px;
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        margin-top: 5px;
    }
    .fill-container {
        flex: 1 1 auto;
    }
}

现在有一个要求是,每当我打开一个盒子时,它应该从包装器中取出50%的高度。因此.box应该height: 50%; .boxes。这意味着,我可以在同一时间内看到最多2个打开的盒子。当我打开第三个等等时,它也应该从.boxs获得50%的相同高度,但是我必须滚动才能看到它。如果我只有一个盒子,它应该在我打开它时填满整个容器,这可以通过ng-class="{fill-container: boxes.length == 1}"解决并且工作正常。我还实现了一个函数,它可以正确地计算和设置50%到.box,并且在屏幕上也是正确的,就像我的截图一样。我是这样做的:

在我的.box-header的ng-click中,我在我的控制器中调用一个名为setBoxHeight()的函数,它计算并设置正确的高度:

<div class="box-header" ng-click="box.open = !box.open; ctrl.setBoxHeight()">
    {{::box.name}}
</div>

该功能如下所示:

setBoxHeight() {
    if (this.boxes.length > 1) {
        let boxHeaderHeight = $('.box-header').outerHeight();
        let halfHeight = Math.round($('.boxes').outerHeight() / 2);

        this.boxes.forEach((box: any) => {
            let element = $('.boxFor' + box.id);
            if (box.open) {
                element.height(halfHeight);
            } else {
                element.height(boxHeaderHeight);
            }
        });
    }
}

如果你比较我的模板和这个函数,应该清楚会发生什么。这也很好。问题是,我必须在不同组件的不同控制器上的每个列表中实现它。我想统一它并集中运行所有列表。它应该是一个干净的解决方案。我尝试构建一个外部组件,并通过一些绑定传递框和它们的类名,并调用一次函数,如下所示:

<my-component items="ctrl.boxes" header-class="'.box-header'" wrapper-class="'.boxes'"></my-component>

我很确定,有一种更清洁的方法可以做到这一点。我希望我的问题很清楚。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可以使用全CSS解决方案,并使用flex-basis属性(请参阅documentation)。基本上,它设置了灵活孩子的默认大小;因此,您可以将其设置为50%,因此每个box的高度为boxes的一半(因为flex-direction设置为column)。

当然有一些实现可以使它适应你的项目,但它值得一试(也许更干净?)。

以下a codepen向您展示了这个技巧。

编辑:正如@MrBuggy指出的那样,这个解决方案在他们的情况下不起作用,因为boxes容器没有固定的高度。