所以我有一个可观察的阵列工作正常,但UI不会更新。我看过很多人遇到这个问题,但是我没有看到它。
所以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上运行)。任何帮助非常感谢!
答案 0 :(得分: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的订阅在每个推文添加时触发一次。如果你想要替换数组,你应该创建一个替换数组,将推文推入该数组,最后通过执行self.tweets(replacementArray);
替换observableArray中的数组。