我使用 Bootstrap 轮播在每个轮播项目中显示两列数据。这是我正在做的一个简化示例:
<div class="carousel-inner col-sm-12" role="listbox" data-bind="foreach: { data: dataSlides, as: 'slide' }">
<div class="item" data-bind="css: { active: $index() == 0 }">
<div class="col-sm-6" data-bind="foreach: { data: dataLeft, as: 'data' }">
<div data-bind="text: data"></div>
</div>
<div class="col-sm-6" data-bind="foreach: { data: dataRight, as: 'data' }">
<div data-bind="text: data"></div>
</div>
</div>
</div>
我的数据模型使用这种结构:
self.dataSlides = ko.observableArray(
[
{ dataLeft: ['data 1', 'data 2', 'data 3'], dataRight: ['data 4', 'data 5', 'data 6'] },
{ dataLeft: ['data 7', 'data 8', 'data 9'], dataRight: ['data 10', 'data 11', 'data 12'] }
]);
这按预期工作,但有一个问题。我显示数据的部分 <div data-bind="text: data"></div>
在我的实际实现中非常复杂,如您所见,我必须写 2 次。一次用于我的左侧数据,一次用于我的右侧数据。
What i would like to do, is to put my data in just one data array (no dataLeft/dataRight) and display half of my data in the left column and the other half in the right column. This way i would not have to write the data display loop twice.
为此,我需要在 foreach 通过一半数据时以某种方式关闭并重新打开列标记。我尝试了以下方法,但这不起作用,因为它破坏了 foreach:
<!-- ko if: $index() == data().length / 2 -->
</div>
<div class="col-sm-6">
<!-- /ko -->
我该怎么做?
最佳答案
我认为修改数据以简化 View 和数据绑定(bind)是个不错的主意。您只是不应该手动执行此操作。
解决这类问题的一个好方法是使用两个变量:
- (可观察的)数据来源:在您的例子中,一组幻灯片
- 一个或多个数据“表示”:数据的自动(
计算
)版本,可以过滤、排序或重组数据以符合您的查看目的。
因此,对于您的情况,我建议使用一个 ko.pureComputed
变量:
- 观察原始数据源并自动计算,
x
行,每y
列,每z
幻灯片。
一个示例实现(不是“最聪明”的实现方式,我试图使其易于阅读......并且不介意样式):
var dataSlides = ko.observableArray(["slide 1","slide 2","slide 3","slide 4","slide 5","slide 6","slide 7","slide 8","slide 9","slide 10","slide 11","slide 12"]);
var dataTable = ko.pureComputed(function() {
var rows = [];
var slidesPerCol = 3;
var colPerRow = 2;
var slidesPerRow = slidesPerCol * colPerRow;
dataSlides().forEach(function(slide, index) {
var rowNr = Math.floor(index / slidesPerRow);
var colNr = Math.floor((index % slidesPerRow) / slidesPerCol);
rows[rowNr] = rows[rowNr] || getRow(colPerRow);
rows[rowNr][colNr].push(slide);
});
return rows;
});
ko.applyBindings({
dataTable: dataTable,
pushSlide: function(){
dataSlides.push("slide " + dataSlides().length);
}
});
// Util
function getRow(c, s) {
return Array(c)
.fill(null)
.map(function() { return []; });
}
.table {
border: 1px solid black;
}
.row {
display: flex;
justify-content: space-between;
}
.row:nth-child(odd) {
background: rgba(0,0,0,0.1);
}
.col {
flex: 1;
display: flex;
flex-direction: column;
justify-content: stretch;
}
.col + .col { border-left: 1px solid black; }
.slide {
flex: 1;
text-align: center;
padding: .5rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: { data: dataTable, as: 'row' }" class="table">
<div data-bind="foreach: { data: row, as: 'col' }" class="row">
<div data-bind="foreach: { data: col, as: 'slide'}" class="col">
<span data-bind="text: slide" class="slide"></span>
</div>
</div>
</div>
<button data-bind="click: pushSlide">add slide</button>
关于html - 使用 knockout 将数据拆分为两个 Bootstrap 列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40993781/