编辑
显然逻辑是正确的。我怀疑问题在于我如何从 API 的 JSON 响应绑定(bind) View 模型。我添加了更多代码来尝试帮助诊断问题。
我是否正确绑定(bind)了 View 模型?
原帖
我不是问如何在 observableArray 中移动项目,我的代码是从这里在数组内上下移动项目: How do I swap two items in an observableArray?
晋升@Michael Best:https://stackoverflow.com/a/10630319/1888402
由@Moes向下移动:https://stackoverflow.com/a/26726556/1888402
我遇到的问题是将项目向下移动。上升得很好,问题似乎出在逻辑上。
JSON 模型
{
"Options": {
"SelectedHeader": "Left Header",
"AvailableHeader": "Right Header"
},
"Selected": [
{
"Order": 2,
"ID": 1,
"Label": "Duration"
},
{
"Order": 11,
"ID": 5,
"Label": "Metres / Min"
},
{
"Order": 23,
"ID": 7,
"Label": "Sprint Dis/Min"
},
{
"Order": 9,
"ID": 15,
"Label": "Max Velocity"
},
{
"Order": 6,
"ID": 16,
"Label": "Hi Intensity Running"
}
],
"Available": [
{
"ID": 123,
"Label": "I'm Available"
}
],
"WebServiceMethodUrl": "../../../Services/SomeAsmxService.asmx/SaveStuff"
}
查看模型
function ViewModel(){
var self = this;
self.Options = model.Options
self.Available = ko.observableArray(model.Available);
self.Selected = ko.observableArray(model.Selected);
self.WebServiceMethodUrl = model.WebServiceMethodUrl;
self.addSelected = function(item){
item.Order = self.Selected().length;
self.Available.remove(item);
self.Selected.push(item);
};
self.removeSelected = function(item){
self.Available.push(item);
self.Selected.remove(item);
};
self.moveUp = function(item) {
var i = self.Selected.indexOf(item);
if (i >= 1) {
var array = self.Selected();
self.Selected().splice(i-1, 2, array[i], array[i-1]); //Works fine
item.Order = i;
}
};
self.moveDown = function(item) {
var i = self.Selected.indexOf(item);
if (i < self.Selected().length - 1) {
var array = self.Selected();
self.Selected().splice(i, 2, array[i + 1], array[i]);
item.Order = i;
self.Selected.valueHasMutated(); //Force rebind
}
};
self.SaveIt = function(){
postDataAsync(self.WebServiceMethodUrl, "{queryString: '"+ ko.toJSON(self) + "'}", "Could not save settings.", function (resp){});
}
self.sortedSelected = ko.computed(function(){
return self.Selected().sort(function(left, right) { return left.Order == right.Order ? 0 : (left.Order < right.Order ? -1 : 1) });
});
}
var vm = new ViewModel();
ko.applyBindings(ViewModel);
HTML 和绑定(bind)
<!-- ko if: sortedSelected().length -->
<tbody data-bind="with:sortedSelected">
<!-- ko foreach: Selected -->
<!-- ko ifnot: (ID == 0) -->
<tr>
<td class="order">
<p data-bind="click: moveUp, clickBubble: false"><i class="fa fa-arrow-up"></i></p>
<p data-bind="text: $index() + 1"></p>
<p data-bind="click: moveDown, clickBubble: false"><i class="fa fa-arrow-down move-down"></i></p>
</td>
<td data-bind="text:Label, attr: { id: ID }"></td>
<td><a class="remove" data-bind="click: removeSelected, clickBubble: false">Remove <i class="fa fa-arrow-circle-o-right"></i></a></td>
</tr>
<!-- /ko-->
<!-- /ko-->
</tbody>
<!-- /ko -->
因此,如果我要对第 5 项调用 moveDown 函数,那么它应该变成第 6 项,而第 6 项应该变成第 5 项。不知道为什么这不起作用,因为这只是逻辑被颠倒了。
示例
最佳答案
问题在于您的 sortedSeleted
计算。任何时候 Selected
被修改时,计算值都会被重新计算,因为它依赖于 Selected
。当计算结果被评估时,它会对 Selected
进行排序。您可能没有意识到 sort
会修改它所调用的数组,同时也会返回该数组。这种按 Order
排序导致 moveUp
和 moveDown
函数显得不一致。
您很可能想要对Selected
的副本进行排序。正如 @RoyJ 指出的,您可以使用 slice
来获取数组的浅拷贝。
关于javascript - 在 ko.observableArray 模型绑定(bind)问题中向下移动项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33018440/