实现Knockout.js破坏性的foreach循环

时间:2016-10-12 04:18:40

标签: javascript arrays knockout.js

这是带有data-bind元素的html:

div data-bind="foreach: clientRequests" id="test2">
           <div class="list-group" >
               <a href="#" class="list-group-item active"><b data-bind="text: client"></b></a>
               <a href="#" class="list-group-item"><b>Priority: </b><b data-bind="text: client_priority"></b></a> 
               <a href="#" class="list-group-item"><b>Title: </b><b data-bind="text: title"></b></a>
               <a href="#" class="list-group-item"><b>Description: </b><b data-bind="text: description"></b></a> 
               <a href="#" class="list-group-item"><b>Product Area: </b><b data-bind="text: product_area"></b></a>
               <a href="#" class="list-group-item"><b>Target Date: </b><b data-bind="text: target_date"></b></a>
               <a href="#" class="list-group-item"><b>Ticket URL: </b><b data-bind="text: ticket_url"></b></a>
           </div>
        </div>

这就是我将一个名为requestsArray的数组传递给foreach循环的方法:

ko.cleanNode(document.getElementById('test2'));

        ko.applyBindings({
            clientRequests: requestsArray
        }, document.getElementById('test2'));

通过各种AJAX调用,返回不同的requestArrays。例如,在初始页面加载之后,进行AJAX调用,该调用接收requestArray的一个实例,该实例可能有10个项目。 foreach循环似乎按预期运行,并且数组中的所有10个项目都填充在页面上。然后,进行第二次AJAX调用,但这次数组可能只有5个项目。会发生的是每个项目重复两次,页面上总共出现10个项目。

问题似乎是,即使之前调用了ko.cleanNode(document.getElementById('test2'))

ko.applyBindings({
                clientRequests: requestsArray
            }, document.getElementById('test2'))

对于每个新数组,每个foreach迭代创建的HTML元素数量随着每个新数组的不断增加而不断增加。使用Vue.js,每次将新数组传递给数据绑定和for循环时,它本质上都是破坏性的,并且不会保留上一次迭代在数组上的任何内容。

显然在这种情况下使用ko.cleanNode并不起作用,我知道in the docs有一个例子可以做我认为正确的过程,但一次只能做一个html元素通过一个按钮和self.array.remove(this),我不太确定如何调整它以完全清除从数组foreach迭代创建的所有html元素。

1 个答案:

答案 0 :(得分:1)

我不明白为什么您必须手动重新应用绑定。具有可观察数组的视图模型的重点是,淘汰赛会为您处理数据更新...通常,当您使用cleanNode时,有一个更简单的方法的东西。

你尝试过这样的事吗?

&#13;
&#13;
// Apply bindings _once_, viewmodel instance does not change
// in between requests
ko.applyBindings(new ViewModel());


function ViewModel() {
  // Because the array is observable, knockout will
  // monitor for changes and update the UI
  this.requests = ko.observableArray([]);
  
  // The view model has the request method
  // the .done callback writes the results to the observable
  // requests array
  this.doRequest = function() {
    mockupAjaxGetter().done(this.requests);
  }.bind(this);
  
  // Do an initial request
  this.doRequest();
};



// Mockup code, just to produce some random numbers on a timeout
function mockupAjaxGetter() {
  var randomResults = [];
  for (var i = 0; i < Math.random() * 20; i += 1) {
     randomResults.push(Math.random()); 
  }
  var cb;
  var applyCb = function() {
    if (cb) cb(randomResults); 
  }
  
  setTimeout(applyCb, 500);
  
  return {
    done: function(fn) { cb = fn; }
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ul data-bind="foreach: requests">
  <li data-bind="text: $data"></li>
</ul>
<button data-bind="click: doRequest">New request</button>
&#13;
&#13;
&#13;