Knockout sortable makes duplicates(制作树状结构)

Knockout sortable makes duplicates (making a tree structure)

我正在使用 Knockout sortable 制作一个可编辑的树结构,并找到了这个很好的例子:http://jsfiddle.net/rniemeyer/Lqttf

这很好用,但我有一个根节点列表,所以我也将根节点绑定更改为可排序的树项列表。 Fiddle: http://jsfiddle.net/yyqnhngm

新模板标记如下所示(注意根 ul 是一个 sortable 绑定,而不是原始的 template):

<script id="nodeTmpl" type="text/html">
    <li>
        <a href="#" data-bind="text: name"></a>
        <div>
           <ul data-bind="sortable: { template: 'nodeTmpl', data: $data.children }"></ul>            
        </div>
    </li>
</script>

<ul data-bind="sortable: { template: 'nodeTmpl', data: root }"></ul>

如果你把B拖到A,那么B会被复制而不是移动到A。这就是我正在寻找原因和解决方案的问题。我的直接想法是 sortable 认为该项目同时被拖入两个列表,可能是因为 markup/html 问题,但我看不出如何。

注意:我知道我可以将所有项目包装到一个根注释中,但这对我的目的来说意义不大。

在我看来,不支持 "ordinary" 数组。将视图模型中的数组更改为 observableArray 可为您提供所需的行为。即:

ko.applyBindings({
  root: ko.observableArray([
    new TreeItem("A", []),
    new TreeItem("B", [])
  ])
});

供参考:

根据 knockout-sortable readme (强调我的)

knockout-sortable is a binding for Knockout.js designed to connect observableArrays with jQuery UI's sortable functionality.

我也试图通过源代码来解释到底出了什么问题,但找不到确切的原因。我确实找到了一个片段,似乎至少解释了作者的想法。

代码显示插件的默认行为使用 splice 方法在数组之间移动元素。这可以解释为什么您的示例没有触发异常:Array.prototypeko.observableArray 都有一个 splice 方法;两者都有相似的论点。

代码块中的最后一条注释解释了 targetParentsourceParent 应该是可观察的。

if (!sortable.hasOwnProperty("strategyMove") || sortable.strategyMove === false) {
  //do the actual move
  if (targetIndex >= 0) {
    if (sourceParent) {
      sourceParent.splice(sourceIndex, 1);

      //if using deferred updates plugin, force updates
      if (ko.processAllDeferredBindingUpdates) {
        ko.processAllDeferredBindingUpdates();
      }
    }

    targetParent.splice(targetIndex, 0, item);
  }

  //rendering is handled by manipulating the observableArray; ignore dropped element
  dataSet(el, ITEMKEY, null);
}

来源:https://github.com/rniemeyer/knockout-sortable/blob/master/src/knockout-sortable.js#L250