【问题标题】:Knockout ObservableArray not updating HTML ForeachKnockout ObservableArray 不更新 HTML Foreach
【发布时间】:2014-02-15 21:41:59
【问题描述】:

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

【问题讨论】:

    标签: javascript knockout.js ko.observablearray


    【解决方案1】:

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

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

    即使您获得了指向正确对象的 this 引用(这可以使用函数具有的 apply 方法,但这不是重点)您仍然不会更新 observableArray,因为您' d 将 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 中的数组。

    【讨论】:

    • 谢谢。我想它可能是这样的,但没有看到它。这立即清除了它。非常感谢您抽出时间用线索棒击败我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-27
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    相关资源
    最近更新 更多