22

我有一个按钮,可以将一个项目在 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");
    }
4

4 回答 4

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]);
    }
}

但是,这仍然不能解决问题,因为 Knockout 仍会将交换视为删除和添加操作。不过,Knockout有一个未解决的问题来支持移动项目。更新:从 2.2.0 版开始,Knockout 可以识别移动的项目,并且foreach绑定不会重新渲染它们。

于 2012-05-17T05:32:07.373 回答
8

我知道这个答案来得有点晚,但我认为它可能对其他想要更通用交换解决方案的人有用。您可以像这样向 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);
    }
}
于 2014-11-04T08:59:24.387 回答
0

我有一个类似的问题,因为我想要 jQuery 拖放我的项目。我的解决方案变成使用 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());
于 2012-04-24T07:55:03.260 回答
0

感谢Michael Best的 moveup 版本

我的 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]);
    }
}
于 2014-11-04T02:02:01.340 回答