Knockout.js ObservalArray.remove在手动修改html后无法正常工作

Knockout.js ObservalArray.remove在手动修改html后无法正常工作,knockout.js,Knockout.js,示例代码在这里。 函数ViewModel(){ var self=这个; 变量ID=[ {id:50,顺序:1}, {id:25,顺序:2}, {id:35,顺序:3} ]; var列表=可观察到的ko(ids); self.sortedList=ko.observearray(); ko.computed(函数(){ var computedList=list().sort(函数(l,r){ 返回l.订单

示例代码在这里。

函数ViewModel(){
var self=这个;
变量ID=[
{id:50,顺序:1},
{id:25,顺序:2},
{id:35,顺序:3}
];
var列表=可观察到的ko(ids);
self.sortedList=ko.observearray();
ko.computed(函数(){
var computedList=list().sort(函数(l,r){
返回l.订单
我基本上希望使用jQueryUISortable插件手动对一行表进行排序。但在手动排序并尝试从observableArray中删除项目后,remove无法正常工作


我彻底搜索了相关问题,似乎在调用ko.cleanNode后需要重新绑定视图模型。这是解决这个问题的唯一办法吗?实际上,我希望避免这种方法,因为我正在使用的数据是动态生成的,并且视图使用了许多模板,因此为重新绑定元素传递正确的数据非常复杂。

问题比您想象的要简单,而且与敲除无关:

对于具有相同
订单
索引的项目,您不会返回
0
。将排序方法更改为:

return l.order === r.order ? 0 : l.order < r.order ? -1 : 1;
为此:

self.sortedList = ko.pureComputed(function() {
    return list().sort(function(l, r){
        var oL = l.order(), 
            oR = r.order();
        return oL === oR
          ? 0 
          : oL < oR ? -1 : 1;
    });
});

订单:

问题比你想象的要简单,而且与击倒无关:

对于具有相同
订单
索引的项目,您不会返回
0
。将排序方法更改为:

return l.order === r.order ? 0 : l.order < r.order ? -1 : 1;
为此:

self.sortedList = ko.pureComputed(function() {
    return list().sort(function(l, r){
        var oL = l.order(), 
            oR = r.order();
        return oL === oR
          ? 0 
          : oL < oR ? -1 : 1;
    });
});

订单:

正如Tomalak所说,它比我想象的要复杂,他给我指出的定制绑定非常有效。

稍后我将发布一个示例代码

编辑
我不知道如何将本地js文件添加到fiddler,所以这次只是一个示例代码。参考knockout-sortable.js,它将为您完成一项工作。在本例中,我不需要计算的可观察项,因为一个项在列表中的位置实际上是由自定义绑定更改的,这正是我想要的。当然,如果您想用其他操作更改列表的顺序,您最有可能需要一个计算的可观察对象来进行排序

<table>
<tbody data-bind="sortable: list" >
<tr>
  <td data-bind="text:id"></td>
  <td ><button data-bind="click:$root.deleteItem">
  delete
  </button></td>
</tr>
</tbody>
</table>

function ViewModel(){
    var self = this;
  var ids = [
    { id:50},
    { id:25},
    { id:35}  
  ];
  self.list = ko.observableArray(ids);
  self.deleteItem = function(item){
    self.list.remove(item);
  }
}    
ko.applyBindings(new ViewModel());

删除
函数ViewModel(){
var self=这个;
变量ID=[
{id:50},
{id:25},
{id:35}
];
self.list=ko.observearray(ids);
self.deleteItem=函数(项目){
self.list.remove(项目);
}
}    
应用绑定(新的ViewModel());

正如Tomalak所说,它比我想象的要复杂,他给我指出的定制绑定非常有效。

稍后我将发布一个示例代码

编辑
我不知道如何将本地js文件添加到fiddler,所以这次只是一个示例代码。参考knockout-sortable.js,它将为您完成一项工作。在本例中,我不需要计算的可观察项,因为一个项在列表中的位置实际上是由自定义绑定更改的,这正是我想要的。当然,如果您想用其他操作更改列表的顺序,您最有可能需要一个计算的可观察对象来进行排序

<table>
<tbody data-bind="sortable: list" >
<tr>
  <td data-bind="text:id"></td>
  <td ><button data-bind="click:$root.deleteItem">
  delete
  </button></td>
</tr>
</tbody>
</table>

function ViewModel(){
    var self = this;
  var ids = [
    { id:50},
    { id:25},
    { id:35}  
  ];
  self.list = ko.observableArray(ids);
  self.deleteItem = function(item){
    self.list.remove(item);
  }
}    
ko.applyBindings(new ViewModel());

删除
函数ViewModel(){
var self=这个;
变量ID=[
{id:50},
{id:25},
{id:35}
];
self.list=ko.observearray(ids);
self.deleteItem=函数(项目){
self.list.remove(项目);
}
}    
应用绑定(新的ViewModel());

这可能是问题之一,但实际上,即使我不使用计算排序列表,它也无法正常工作。很遗憾,你的代码也帮不上忙。不管怎样,谢谢事实上,在你的小提琴中,它似乎起了作用:不过我会对我的答案再加一些解释。。。如果编辑中的代码对您不起作用,希望它会有所帮助,问题在于jQuery插件。如果它从DOM中删除了数据绑定元素,那么knockout可能会失去与表的连接。感谢您花时间进行详细解释。是的,我知道如果我想用order属性对列表进行排序,我需要使其可见,但我不想这样做,这就是我调用vm.list.valueHasMutated()的原因;更新订单后。但无论如何,是的,我同意你的看法,可能jquery小部件失去了敲除连接,这就是我猜测的,也是我在第一个问题中询问如何在更新订单后重新绑定项目的原因。我需要jquery小部件功能,所以我想重新绘制项目,您认为我需要在这种情况下使用ko.cleanNode吗?通常,必须使用
cleanNode
是一个坏迹象。。。你找过现成的定制装订吗?也许您可以提供一个显示实际错误/问题的示例,包括可排序库。如果可以的话,我可以看一看并提供一个更精确的答案……嗯,这可能是问题之一,但实际上,即使我不使用计算排序列表,它也不会正常工作。很遗憾,你的代码也帮不上忙。不管怎样,谢谢事实上,在你的小提琴中,它似乎起了作用:不过我会对我的答案再加一些解释。。。如果编辑中的代码对您不起作用,希望它会有所帮助,问题在于jQuery插件。如果它从DOM中删除了数据绑定元素,那么knockout可能会失去与表的连接。感谢您花时间进行详细解释。是的,我知道如果我想用order属性对列表进行排序,我需要使其可见,但我不想这样做,这就是我调用vm.list.valueHasMutated()的原因;更新订单后。但无论如何,是的,我同意