Knockout.js 如何在一个可观察的阵列中交换两个项目?

Knockout.js 如何在一个可观察的阵列中交换两个项目?,knockout.js,Knockout.js,我有一个按钮,可以将一个项目在可观察的轨道上向左移动一个位置。我是这样做的。但是,缺点是categories()[index]会从数组中删除,从而丢弃该节点上的任何DOM操作(在我的例子中是通过jQuery验证) 有没有办法在不使用临时变量的情况下交换两个项以保留DOM节点 moveUp: function (category) { var categories = viewModel.categories; var length = categories

我有一个按钮,可以将一个项目在可观察的轨道上向左移动一个位置。我是这样做的。但是,缺点是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");
    }

我有一个类似的问题,因为我希望jQuery拖放到我的项目上。 我的解决方案是使用knockoutjs模板将beforeRemove和afterAdd事件绑定到模型中。Person类/函数也是一个简单的淘汰视图模型

在下面的示例中,我使用.draggable(),但您可以轻松地使用验证。添加您自己的代码来操作observableArray,您应该可以开始了

HTML:


以下是我的
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仍然会将交换视为删除和添加操作。不过,有一个用于击倒以支持移动项目的工具。更新:从2.2.0版开始,Knockout可以识别移动的项目,foreach的
绑定将不会重新呈现这些项目。

感谢他的moveup版本

我的移动版本

moveDown: function(category) {
    var array = categories();
    var i = categories.indexOf(category);
    if (i < arr.length) {
        categories.splice(i, 2, array[i + 1], array[i]);
    }
}
moveDown:功能(类别){
var数组=categories();
var i=类别。indexOf(类别);
如果(i
我知道这个答案来得有点晚,但我认为它可能对其他想要更通用交换解决方案的人有用。您可以向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);
    }
}

你能详细说明吗?我试图做的是使用按钮允许用户排序(稍后可能实现拖放)。处理beforeRemove和afterAdd如何保留DOM元素?DOM元素是通过敲除生成的,但通过jQuery验证进行了更改,我通过从中删除然后重新插入该项而丢失了更改。在我的示例中,我只是在将该项重新添加到DOM中时,在您的验证中,重新添加可拖动项。在我的例子中,它不需要保留任何状态变量(它们都在模型中),因此它对我有效。验证不也应该是一样的吗?非常感谢,这里是在IE 11中不起作用的下移示例。大卫·布朗的方法成功了。你的版本不正确。将“arr.length”替换为“array.length-1”就可以做到这一点。即使在IE 11中,效果也很好。
myArray.swap(index1, index2);
moveUp: function(category) {
    var i = categories.indexOf(category);
    if (i > 0) {
        categories.swap(i, i+1);
    }
}