如何在observableArray中交换两个项目?

Jeo*_*uan 21 knockout.js

我有一个按钮,可以将项目移动到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");
    }
Run Code Online (Sandbox Code Playgroud)

Mic*_*est 35

这是我的版本,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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这仍然无法解决问题,因为Knockout仍会将交换视为删除和添加操作.但是Knockout 有一个未解决的问题就是支持移动物品.更新:从版本2.2.0开始,Knockout确实识别移动的项目,foreach绑定不会重新呈现它们.


Dav*_*own 8

我知道这个答案有点迟了,但我认为对于那些想要更通用的交换解决方案的人来说这可能是有用的.您可以向observableArrays添加交换函数,如下所示:

ko.observableArray.fn.swap = function(index1, index2) {
    this.valueWillMutate();

    var temp = this()[index1];
    this()[index1] = this()[index2];
    this()[index2] = temp;

    this.valueHasMutated();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用此函数在给定索引的情况下交换数组中的两个元素:

myArray.swap(index1, index2);
Run Code Online (Sandbox Code Playgroud)

对于moveUp函数,您可以执行以下操作:

moveUp: function(category) {
    var i = categories.indexOf(category);
    if (i > 0) {
        categories.swap(i, i+1);
    }
}
Run Code Online (Sandbox Code Playgroud)