2014-02-15 71 views
9

所以我有一个可以正常工作的observablearray,但UI不更新。我读过很多人遇到过这类问题,但我没有看到它。Knockout ObservableArray不更新HTML Foreach

因此,HTML是

  <tbody data-bind="foreach: tweets"> 
      <tr> 
       <td> 
        <span data-bind="visible: created_at" class="label label-success">Yup</span> 
       </td> 
       <td><p><b data-bind="text: screen_name"></b></p></td> 
       <td><p><b data-bind="text: id"></b></p></td> 
       <td><p data-bind="text: text"></p></td> 
       <td><p data-bind="text: created_at"></p></td> 
      </tr> 
      </tbody> 

和JavaScript是调用API,并从它建立一个数组的函数。

<script type="text/javascript"> 
     function TweetsViewModel() { 
      var self = this; 
      self.tasksURI = 'http://localhost:8000/api/v1/tweet/'; 
      self.tweets = ko.observableArray(); 

      self.ajax = function(uri, method, data) { 
       var request = { 
        url: uri, 
        type: method, 
        contentType: "application/json", 
        Accept: "application/json", 
        cache: false, 
        dataType: 'json', 
        data: JSON.stringify(data) 
       }; 
       return $.ajax(request); 
      } 

      self.ajax(self.tasksURI, 'GET').done(function(data) { 
       for (var i = 0; i < data.objects.length; i++) { 
        var tweet = this; 
        tweet.created_at = ko.observable(data.objects[i].created_at) 
        tweet.text = ko.observable(data.objects[i].text) 
        tweet.id = ko.observable(data.objects[i].id) 
        tweet.screen_name = ko.observable(data.objects[i].twitteruser.screen_name) 
        self.tweets.push(tweet) 
       } 
      }); 
      setTimeout(TweetsViewModel, 10000) 
     } 
     ko.applyBindings(new TweetsViewModel()); 
    </script> 

仅用于测试目的,我使用setTimeout来重新运行对API的调用并更新数组。数组得到正确更新,但UI不。我为自己的无知道歉(长期以来一直是后端开发者,这是我10年来首次使用Javascript)。任何帮助非常感谢!

回答

3

问题是你永远不会更新observableArray。

首先,您再次调用构造函数,但this引用可能不指向您认为的对象。当您再次呼叫TweetsViewModel构造函数时(在呼叫setTimeout中),this参考将指向window对象。

即使你得到的this引用指向正确的对象(这可能使用apply方法,功能有,但这是旁边的),你仍然不会更新observableArray,因为你会设置在self.tweets变量到一个新的observableArray上线

self.tweets = ko.observableArray(); 

所有订阅,如UI DOM元素仍然会订阅旧的observableArray,因为他们不知道变量已经改变。

所以,你应该做的是建立执行重新加载数据的功能,如下所示:也

self.reloadData = function(){ 
    self.ajax(self.tasksURI, 'GET').done(function(data) { 
     for (var i = 0; i < data.objects.length; i++) { 
      // Important: Create a new tweet object instead of using 'this' here. 
      var tweet = {}; 
      tweet.created_at = ko.observable(data.objects[i].created_at) 
      tweet.text = ko.observable(data.objects[i].text) 
      tweet.id = ko.observable(data.objects[i].id) 
      tweet.screen_name = ko.observable(data.objects[i].twitteruser.screen_name) 
      self.tweets.push(tweet) 
     } 
    }); 
} 
setTimeout(self.reloadData, 10000); 

,要知道,这会随时添加鸣叫的observableArray(从来没有明确它),并且它会导致订阅到observableArray,每添加一条鸣叫一次。如果你想要替换数组,你可能应该创建一个替换数组,将tweets推入该数组,最后通过执行self.tweets(replacementArray);替换observableArray中的数组。

+0

谢谢。我认为这可能是这样的,但没有看到它。这清除了它的权利。我真的很感谢你用时间棒击败我。 – user3314493

相关问题