0

一周前我刚开始使用 knockout.js,所以希望这很容易。我花了大约 5 个小时搜索 Google 和这个网站,但我看到的所有建议似乎都不起作用。我尝试将 pagedPlayerList 更改为仅 playerList 以删除该部分代码作为问题。

我有这段代码显示了一些带有 knockout.js 的数据

<table class="table table-striped table-bordered">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Attack</th>
                        <th>Defense</th>
                        <th>Level</th>
                        <th>IPH</th>
                        <th>Syndicate</th>
                        <th>Last Modified</th>
                        <th style="width: 100px; text-align:right;" />
                    </tr>
                </thead>
               <tbody data-bind=" template:{name:playerTemplateToUse, foreach: pagedPlayerList }"></tbody>
            </table>

            <ul class="pagination">
                <li data-bind="css: { disabled: pageIndex() === 0 }"><a href="#" data-bind="click: previousPage">&laquo;</a></li>
            </ul>
            <ul class="pagination" data-bind="foreach: allPlayerPages">
                <li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.moveToPage($data.pageNumber-1); }"></a></li>
            </ul>
            <ul class="pagination">
              <li data-bind="css: { disabled: pageIndex() === maxPlayerPageIndex() }"><a href="#" data-bind="click: nextPlayerPage">&raquo;</a></li>
            </ul>

            <script id="itemsPlayerTmpl" type="text/html">
               <tr>
                    <td data-bind="text: id"></td>
                    <td data-bind="text: name"></td>
                    <td data-bind="text: att"></td>
                    <td data-bind="text: def"></td>
                    <td data-bind="text: lvl"></td>
                    <td data-bind="text: iph"></td>
                    <td data-bind="text: synd_name"></td>
                    <td data-bind="text: $root.lastModDate(last_modified)"></td>
                    <td class="buttons">
                        <a class="btn btn-sm btn-primary" data-bind="click: $root.edit" href="#" title="edit"><i class="glyphicon glyphicon-edit"></i></a>
                        <a class="btn btn-sm btn-primary" data-bind="click: $root.removePlayer" href="#" title="remove"><i class="glyphicon glyphicon-remove"></i></a>
                    </td>
                </tr>
            </script>

            <script id="editPlayerTmpl" type="text/html">
                <tr>
                    <td data-bind="text: id"></td>
                    <td><input data-bind="value: name"/></td>
                    <td><input size="8" data-bind="value: att"/></td>
                    <td><input size="8" data-bind="value: def"/></td>
                    <td><input size="3" data-bind="value: lvl"/></td>
                    <td><input size="8" data-bind="value: iph"/></td>
                    <td>
                       <select data-bind="options: $root.syndList, optionsText: 'name', optionsValue: 'id', value: synd_id, selectedOptions: 'synd_id', optionsCaption: 'Please select...'"></select>
                    </td>

                    <td data-bind="text: $root.lastModDate(last_modified)"></td>
                    <td class="buttons">
                        <a class="btn btn-sm btn-success" data-bind="click: $root.savePlayer" href="#" title="save"><i class="glyphicon glyphicon-ok"></i></a>
                        <a class="btn btn-sm btn-primary" data-bind="click: $root.cancel" href="#" title="cancel"><i class="glyphicon glyphicon-trash"></i></a>
                    </td>
                </tr>
            </script>

加载页面时它可以完美运行。问题是,我想让数据每 2 分钟自动更新一次,并且当我加载显示中的数据时不会更新。

这是javascript的相关部分

        self.playerList = ko.observableArray();
        <?php if(isset($playerlist)) { ?>
            self.playerList(jQuery.parseJSON('<?php echo addslashes($playerlist); ?>'));
        <?php } ?>

        self.lastModDate = function(data){
            var myDate = new Date(data * 1000);
            var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
            var month = months[myDate.getMonth()];
            var date = myDate.getDate();
            var year = myDate.getFullYear();
            var time = date+', '+month+' '+year;
            return time;
        }
        // ALL PLAYERS TAB       
        self.addPlayer = function () {
            var newItem = new Player();
            self.playerList.push(newItem);
            self.selectedItem(newItem);
            self.moveToPage(self.maxPlayerPageIndex());
        };
        self.removePlayer = function (item) {
            if (item.id) {
                if (confirm('Are you sure you wish to delete this item?')) {
                    $.post('<?php echo base_url('front/deleteplayer'); ?>', item).complete(function (result) {
                        if(result = '1'){
                            toastr.success("The player has been removed.", "");
                            self.playerList.remove(item);
                            if (self.pageIndex() > self.maxPlayerPageIndex()) {
                                self.moveToPage(self.maxPlayerPageIndex());
                            }
                        } else {
                            toastr.error("There was a problem removing the player", "");
                        }
                    });
                }
            }
            else {
                self.list.remove(item);
                if (self.pageIndex() > self.maxPlayerPageIndex()) {
                    self.moveToPage(self.maxPlayerPageIndex());
                }
            }
        };
        self.savePlayer = function () {
            var item = self.selectedItem();
            $.post('<?php echo base_url('front/saveplayer'); ?>', item, function (result) {
                console.log(item);
                toastr.success("Your changes have been saved.", "");
                self.selectedItem(null);
            });

        };
        self.pagedPlayerList = ko.dependentObservable(function () {
            var size = self.pageSize();
            var start = self.pageIndex() * size;
            return self.playerList().slice(start, start + size);
        });
        self.maxPlayerPageIndex = ko.dependentObservable(function (list) {
            return Math.ceil(self.playerList().length / self.pageSize()) - 1;
        });
        self.nextPlayerPage = function () {
            if (self.pageIndex() < self.maxPlayerPageIndex()) {
                self.pageIndex(self.pageIndex() + 1);
            }
        };
        self.allPlayerPages = ko.dependentObservable(function () {
            var pages = [];
            for (i = 0; i <= self.maxPlayerPageIndex() ; i++) {
                pages.push({ pageNumber: (i + 1) });
            }
            return pages;
        });
        self.playerTemplateToUse = function (item) {
            return self.selectedItem() === item ? 'editPlayerTmpl' : 'itemsPlayerTmpl';
        };
        // END ALL PLAYERS TAB

        self.edit = function (item) {
            self.selectedItem(item);
            self.currentSynd(item.synd_id);
        };

        self.cancel = function () {
            self.selectedItem(null);
        };
        self.previousPage = function () {
            if (self.pageIndex() > 0) {
                self.pageIndex(self.pageIndex() - 1);
            }
        };
        self.moveToPage = function (index) {
            self.pageIndex(index);
        };

然后这是绑定/更新代码

    // SELF UPDATING DATA
    update = function() {
        siteModel.updatePlayerList();
        console.log(siteModel.playerList);
    }

    var siteModel = new siteModel();
    window.setInterval(update,60000);
    ko.applyBindings(siteModel);

这是 updatePlayerList 函数

        self.updatePlayerList = function(){
            $.ajax({
                url:'<?php echo base_url('front/listplayers'); ?>',
                success:function(data) {
                    var obj = jQuery.parseJSON(data);
                    self.playerList = (obj);
                }
            });
        }

updatePlayerList 第一次触发这是服务器返回内容的摘录:

[{"id":"19","name":"AlDavisJR","att":"818741","def":"895287","lvl":"227","iph":"2804866","synd_id":"9","last_modified":"1384284327","synd_name":"FIGHT CLUB"},{"id":"15","name":"aLEX","att":"95748","def":"112386","lvl":"227","iph":"16033","synd_id":"15","last_modified":"1384240593","synd_name":"iron"}]

但是 console.log(self.playerList); 显示一个空白值。它运行 console.log 的第二次和任何后续时间都会显示正确的数据。

问题是表格总是显示页面首次加载时加载的数据。如果我修改数据库,ajax 调用会取回新数据,但不会上传网站。

4

1 回答 1

0

有很多代码,所以可能还有更多代码,但我发现的第一件事是你在 self.updatePlayerList 函数中更新了错误的数据。

var obj = jQuery.parseJSON(data);
self.playerList = (obj); // This assigns obj to self.playerList, overwriting the observableArray

而是做

self.playerList(obj); // This keeps the observable intact, and assigns obj as it's new internal value

让我知道这是否为您解决了问题!

编辑:

另外,你的console.log第一次是空白的原因是因为updatePlayerList是一个异步函数(因为你的ajax调用是异步执行的)。因此将调用 ajax 函数,并且在它检索数据时,您已经将 observableArray 的值输出到控制台。相反,您需要等到成功回调触发,然后登录到那里的控制台以检查值是否正确。

另一个可能有用的提示:当您将 observable 记录到控制台时,您不会看到 observable 的实际值。辅助函数对检索(嵌套)可观察对象ko.toJS(yourObservableHere)ko.toJSON(yourObservableHere)实际值非常有帮助。第一个使用您放入的任何内容(删除可观察的包装器)制作一个普通的 javascript 对象,第二个做同样的事情,但将其全部输出到 JSON 字符串。这对于在 UI 中进行调试很有用(例如<div data-bind="text: ko.toJSON(yourViewModel)"></div>

于 2013-11-12T20:16:11.017 回答