javascript - Knockout ObservableArray 不更新 HTML Foreach

标签 javascript knockout.js ko.observablearray

所以我有一个可以正常工作的 observablearray,但是 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 的调用并更新数组。 Array 得到正确更新,但 UI 没有。我为我的无知而道歉(长期以来一直是后端开发人员,这是我 10 年来第一次使用 Javascript)。非常感谢任何帮助!

最佳答案

问题是您永远不会更新 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 中的数组。

关于javascript - Knockout ObservableArray 不更新 HTML Foreach,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21804009/

相关文章:

javascript - Webpack 正在破坏我的 .scss 样式表类

javascript - ObservableArray 绑定(bind)不会更新

javascript - knockout .js |可观察数组仅在最后一个元素更改时触发

jquery - 如果 iframe src 加载失败,则捕获错误。错误 : -"Refused to display ' http://www. google.co.in/' in a frame.."

knockout.js - 我如何在 knockout 数组中的特定索引处插入元素

javascript - 如何从 Drupal 7 中的特定内容类型中删除 CSS 和 JS

javascript - 没有 Canvas 的 HTML5 getImageData

javascript - 拖动未分组在 `g` 标记中的多个元素?

javascript - observableArray 替换不更新 UI