2014-02-15 74 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

相關問題