我正在尝试使用 knockout js 创建一个包含 4 行和 4 列的表格。下面是我的数组,其中包含 16 个元素,需要将这些元素放入表格中。
/*----------------------------------------------------------------------*/
/* View Model */
/*----------------------------------------------------------------------*/
function ViewModel() {
var self = this;
self.items = ko.observableArray(["1.jpg",
"2.jpg",
"3.jpg",
"4.jpg",
"5.jpg",
"6.jpg"
]);
self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
var rows = [];
var count = 0;
var items = self.items(); //get the item array
var current = [];
for(var i in items)
{
var item = items[i];
current.push(item);
count++;
if (count == 4)
{
count = 0;
rows.push(current);
current = []; //next array
}
}
if (current.length > 0)
{
rows.push(current);
}
return rows;
});
self.bindSort = function() {
var startIndex = -1;
var sortableSetup = {
start: function (event, ui)
{
startIndex = ui.item.index();
},
stop: function (event, ui)
{
var newIndex = ui.item.index();
if (startIndex > -1)
{
self.from = ko.observable(startIndex);
self.to = ko.observable(newIndex);
var iTo = parseInt(self.to());
var iFrom = parseInt(self.from());
var from = self.items()[iFrom];
var to = self.items()[iTo];
self.items()[iTo] = from;
self.items()[iFrom] = to;
//alert('before');
// alert(from);
// alert(to);
var fromA = self.items()[iFrom];
var toA = self.items()[iTo];
//alert('after');
//alert(fromA);
// alert(toA);
self.items.remove(from);
self.items.splice(newIndex, 0, toA);
self.items.remove(to);
self.items.splice(startIndex, 0, fromA);
//ui.item.remove();
self.items.valueHasMutated();
}
}
};
$(".fruitList").sortable( sortableSetup );
};
}
/*----------------------------------------------------------------------*/
/* KO HTML Binding */
/*----------------------------------------------------------------------*/
$(document).ready(function() {
// create the view model
var model = new ViewModel();
// call the bind method for jquery UI setup
model.bindSort();
// binds ko attributes with the html
ko.applyBindings(model);
});
并尝试在 html 中执行此操作,
<table data-bind="foreach: itemRows">
<tr class="fruitList" data-bind="foreach: $data">
<td><img data-bind="attr: { src: $data }" /></td>
</tr>
</table>
我无法获取数组的长度,也无法在第一行创建 4 个 tds 并创建第二行后如何打破循环。有什么建议吗???
更新:
当我使用 sortable 时,下面的代码似乎不起作用,
start: function (event, ui)
{
startIndex = ui.item.index();
},
stop: function (event, ui)
{
var newIndex = ui.item.index();
最佳答案
更新:移动到可排序版本的底部
不可排序版本
在您编辑和提到排序之前,我创建了一个似乎满足您要求的 jsfiddle:http://jsfiddle.net/fENSD/4/
我所做的是创建一个计算的可观察对象,它观察您的可观察项目并返回一个嵌套数组,其形状是您想要用于表格渲染的。这不是最有效的函数,但通过一些工作,您可能会减少分配的数组数量(目前,每次更新时都会为 4x4 网格创建 5 个左右):
self.items = ko.observableArray(["images/1.jpg", "images/2.jpg", "images/3.jpg", "images/4.jpg", "images/5.jpg", "images/6.jpg"]);
self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
var rows = [];
var count = 0;
var items = self.items(); //get the item array
var current = [];
for(var i in items)
{
var item = items[i];
current.push(item);
count++;
if (count == 4)
{
count = 0;
rows.push(current);
current = []; //next array
}
}
if (current.length > 0)
{
rows.push(current);
}
return rows;
});
然后表格呈现如下:
<table data-bind="foreach: itemRows">
<tr data-bind="foreach: $data">
<td><img data-bind="attr: { src: $data }" /></td>
</tr>
</table>
JSFiddle 包含一个示例,该示例将一个项目添加到 items observable 中,并更新表以反射(reflect)这一点,如果您希望看到它的实际效果。 JSFiddle 中还有一个示例,说明您可以通过一种方式获取项目数组的长度 (data-bind="text: items().length"
)。
排序版本
这是一个很大的变化,但我也设法让排序工作正常。以 jquery ui 网站为例,我得到以下内容:
很难对表进行排序,因此 jquery ui 示例实际上使用了一个列表,该列表具有定义的宽度,每个元素占据一定的宽度。这有效地创建了一个表。我假设由于您使用的是图像,所以您可以使它们的大小完全相同。
为此,我有一些像这样的 CSS:
#items { list-style-type: none; margin: 0; padding: 0; width: 200px; }
#items li { width: 48px; margin: 0px; padding: 0px; float: left; text-align: center; height: 48px; }
然后我像这样创建了一个合适的绑定(bind)处理程序:
ko.bindingHandlers['sortable'] = {
init: function (element, valueAccessor) {
var $element = $(element);
var observable = valueAccessor();
var value = ko.utils.unwrapObservable(observable);
$element.sortable({
stop: function(event, ui) {
var prev = ui.item.prev();
var data = ko.dataFor(ui.item[0]);
var index = 0;
if (prev.length > 0) {
//not the first item
var prevData = ko.dataFor(prev[0]);
var index = value.indexOf(prevData) + 1;
}
var oldIndex = value.indexOf(data);
value.splice(oldIndex, 1);
value.splice(index, 0, data);
observable.valueHasMutated();
}
});
}
};
每当 sortable 更新时,它都会修改传递给绑定(bind)的可观察数组。 注意:这是非常不稳健的,需要检查以确保传递的值实际上是可观察的,然后再告诉它它的值已经发生变化。
View 模型如下所示:
function ViewModel() {
var self = this;
self.items = ko.observableArray(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"]);
self.items.subscribe(function (value) {
console.log(value); //this is so you can see that the array is indeed being re-sorted
});
self.add = function () {
self.items.push("another thing");
};
}
并渲染:
<ul id="items" data-bind="sortable: items, foreach: items">
<li><img data-bind="attr: { src: $data }" /></li>
</ul>
此方法的局限性在于,如果您的项目大小不同,则 sortable 的顺序看起来与内存中实际表示的顺序略有不同。但是,只要所有元素的大小都相同,它应该可以正常工作。另一个问题是这不适用于重复项。然而,要解决这个问题,只需让每个元素成为包含一个值(甚至可能是一个可观察值)的对象,而不是一个普通的旧字符串。
关于javascript - 动态行创建挖空js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15105737/