我有一个按钮,可以将项目移动到observableArray中的一个位置。我是按照以下方式做的。但是,缺点是categories()[index]会从数组中删除,从而丢弃该节点上的任何DOM操作(在我的情况下通过jQuery验证)。
有没有办法在不使用临时变量的情况下交换两个项目以保留DOM节点?
moveUp: function (category) {
var categories = viewModel.categories;
var length = categories().length;
var index = categories.indexOf(category);
var insertIndex = (index + length - 1) % length;
categories.splice(index, 1);
categories.splice(insertIndex, 0, category);
$categories.trigger("create");
}
答案 0 :(得分:36)
这是我的moveUp
版本,可以一步完成交换:
moveUp: function(category) {
var i = categories.indexOf(category);
if (i >= 1) {
var array = categories();
categories.splice(i-1, 2, array[i], array[i-1]);
}
}
但仍然无法解决问题,因为Knockout仍会将交换视为删除和添加操作。但是Knockout有一个open issue来支持移动项目。 更新:从版本2.2.0开始,Knockout会识别已移动的项目,foreach
绑定不会重新呈现它们。
答案 1 :(得分:6)
我知道这个答案有点迟了,但我认为对于那些想要更通用的交换解决方案的人来说这可能是有用的。您可以向observableArrays添加交换函数,如下所示:
ko.observableArray.fn.swap = function(index1, index2) {
this.valueWillMutate();
var temp = this()[index1];
this()[index1] = this()[index2];
this()[index2] = temp;
this.valueHasMutated();
}
然后,您可以使用此函数在给定索引的情况下交换数组中的两个元素:
myArray.swap(index1, index2);
对于moveUp函数,您可以执行以下操作:
moveUp: function(category) {
var i = categories.indexOf(category);
if (i > 0) {
categories.swap(i, i+1);
}
}
答案 2 :(得分:0)
我有一个类似的问题,因为我想要jQuery drag& amp;放下我的物品。 我的解决方案是使用knockoutjs模板将beforeRemove和afterAdd事件绑定到模型。 Person类/函数也是一个简单的挖空视图模型。
在下面的示例中,我使用.draggable(),但您可以轻松使用验证。添加自己的代码来操作observableArray,你应该好好去。
HTML:
<div data-bind="template: {foreach:attendeesToShow, beforeRemove:hideAttendee, afterAdd:showAttendee}">
<div class="person">
<img src="person.jpg" alt="" />
<div data-bind="text: firstName" ></div>
<div class="deleteimg" data-bind="click:$parent.removeAttendee" title="Remove"></div>
</div>
</div>
视图模型:
var ViewModel = function () {
var self = this;
var at = [new Person('First', 'Person', 'first@example.com'),
Person('Second', 'Person', 'second@example.com')
];
self.attendees = ko.observableArray(at);
self.removeAttendee = function (attendee) {
self.attendees.remove(attendee);
};
this.showAttendee = function (elem) {
if (elem.nodeType === 1) {
$(elem).hide().show("slow").draggable();//Add jQuery functionality
}
};
this.hideAttendee = function (elem) {
if (elem.nodeType === 1) {
$(elem).hide(function () {
$(elem).remove();
});
}
};
};
ko.applyBindings(new ViewModel());
答案 3 :(得分:0)
感谢Michael Best他的移动版本
我的moveDown版本
moveDown: function(category) {
var array = categories();
var i = categories.indexOf(category);
if (i < arr.length) {
categories.splice(i, 2, array[i + 1], array[i]);
}
}