【问题标题】:Knockout nested sortable sourceParent.splice is not a function淘汰嵌套的可排序 sourceParent.splice 不是函数
【发布时间】:2016-04-26 13:19:31
【问题描述】:

在这里,我正在编写使用 Knockout 可排序的代码。它应该显示嵌套的可排序 3 层以上的深度。

数据被传递到模板中,但有些元素被丢弃后又回到了原来的位置(例如最上层的A、B元素)。

我应该如何配置嵌套的可排序,以便最上层也可以使用而不会出错?

错误:

knockout-sortable.js:244 Uncaught TypeError: sourceParent.splice is not a function

或

knockout-sortable.js:252 Uncaught TypeError: targetParent.splice is not a function

JSFiddle - Similar working example

var viewModel = function() {
  var self = this;
  self.children = ko.observable([{
    "name": "A",
    "children": [{
      "name": "A1",
      "children": [{
        "name": "A11"
      }, {
        "name": "A12"
      }]
    }, {
      "name": "A2"
    }]
  }, {
    "name": "B",
    "children": [{
      "name": "B1"
    }, {
      "name": "B2"
    }]
  }]);
}
ko.applyBindings(new viewModel());
ul {
  border: solid 1px green;
  list-style-type: none;
  margin:0px;
}
li {
  padding: 10px;
  border: solid 1px blue;
  margin:0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>

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

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

【问题讨论】:

    标签: knockout.js knockout-2.0 knockout-3.0 knockout-sortable knockout-templating


    【解决方案1】:

    Peter Gerhat提供的解决方案不正确。 问题是使用了数组的observable,而不是observableArray。

    错误指出sourceParent(这是从中拖动元素的视图模型上的集合)没有splice 函数。这是正确的,observable 没有 splice 函数,而 array 或 observableArray 有。这同样适用于targetParent(它是元素被拖动到的视图模型上的集合)。

    要使初始示例正常工作,只需将observable 更改为observableArray。

    但是,正如您会在原始示例和Peter Gerhat 提供的解决方案中注意到的那样,即使没有抛出错误,它仍然不能真正发挥应有的作用。您会注意到,当您拖动元素时,要么根本不动,要么消失。

    这里的解决方案是将每个array变成observableArray,这样它们就可以被sortable绑定更新。

    var viewModel = function() {
      var self = this;
      self.children = ko.observableArray([{
        "name": "A",
        "children": ko.observableArray([{
          "name": "A1",
          "children": ko.observableArray([{
            "name": "A11"
          }, {
            "name": "A12"
          }])
        }, {
          "name": "A2"
        }])
      }, {
        "name": "B",
        "children": ko.observableArray([{
          "name": "B1"
        }, {
          "name": "B2"
        }])
      }]);
    }
    ko.applyBindings(new viewModel());
    ul {
      border: solid 1px green;
      list-style-type: none;
      margin: 0px;
    }
    
    li {
      padding: 10px;
      border: solid 1px blue;
      margin: 0px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>
    
    <script id="nodeTmpl" type="text/html">
      <li>
        <!-- ko if: $data.name -->
        <a href="#" data-bind="text: $data.name"></a>
        <!-- /ko -->
        <!-- ko if: $data.children -->
        <ul data-bind="sortable: { template: 'nodeTmpl', data: $data.children }"></ul>
        <!-- /ko -->
      </li>
    </script>
    
    <ul data-bind="sortable: { template: 'nodeTmpl', data: $root.children }"></ul>

    【讨论】:

      【解决方案2】:

      通过更改行 &lt;ul data-bind="template: { name: 'nodeTmpl', data: $root }"&gt;&lt;/ul&gt; 解决了问题,我从一些引用中删除了 $data,因为它导致了错误。

      var viewModel = function() {
          var self = this;
          self.children = [{
          "name": "A",
          "children": [{
            "name": "A1",
            "children": [{
              "name": "A11",
            }, {
              "name": "A12",
            }]
          }, {
            "name": "A2",
          }]
        }, {
          "name": "B",
          "children": [{
            "name": "B1",
          }, {
            "name": "B2",
          }]
        }]
      };
      ko.applyBindings(new viewModel());     
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
      <script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>
      
      <script id="nodeTmpl" type="text/html">
        <li>
          <!-- ko if: $data.name -->
          <a href="#" data-bind="text: name"></a>
          <!-- /ko -->
          <!-- ko if: $data.children -->
          <ul data-bind="sortable: { template: 'nodeTmpl', data: children }"></ul>
          <!-- /ko -->
        </li>
      </script>
      
      <ul data-bind="template: { name: 'nodeTmpl', data: $root }"></ul>

      【讨论】:

      • 提供的 sn-p 仍然不起作用。虽然错误消失了,但拖动会使元素要么不移动,要么完全消失。我已经发布了解决这些问题的答案。此外,没有必要删除 $data 块。
      猜你喜欢
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-14
      相关资源
      最近更新 更多