如何迭代Knockout ObservableArray?(长度0)

How to iterate an Knockout ObservableArray? (length 0)

本文关键字:长度 ObservableArray Knockout 迭代 何迭代      更新时间:2023-09-26

我是knockout.js的新手(这也是我的第一篇stackoverflow帖子),现在我面临以下问题。

我无法将web api中的数据绑定到ko.observabrarray。为什么这个公告ko.obsrvabrarray的长度总是0?该代码可以很好地处理客户端数据(通过添加新的公告)。。

这是JS代码:

var AnnouncementModel = function () {
    var self = this;
    self.AnnouncementText = ko.observable();
    self.AllDepartmentsBool = ko.observable();
    self.Editable = ko.observable(false);
    self.Add = function () {
        viewModel.Announcements.push(self);
        viewModel.AnnouncementToEdit(new AnnouncementModel());
    };
    self.Delete = function () {
        ajaxHelper(announcementsUri + self.ID, 'DELETE').done(
        viewModel.Announcements.remove(self));
    };
    self.Edit = function () {
        self.Editable(!self.Editable());
    };
}
//The ViewModel
function AnnouncementsViewModel() {
    var self = this;
    self.InitialData = ko.observableArray();
    self.Announcements = ko.observableArray();
    self.AnnouncementToEdit = ko.observable(new AnnouncementModel());
    self.error = ko.observable();
    function getAllAnnouncements() {
        ajaxHelper(announcementsUri, 'GET').done(function(data) {
            self.InitialData(data);        
        });
    };
    getAllAnnouncements();
};
var viewModel = new AnnouncementsViewModel();
ko.applyBindings(viewModel, document.getElementById("announcements-container"));
function createAnnouncement(announcementDto) {
    var announcement = new AnnouncementModel();
    announcement.AnnouncementText = ko.observable(announcementDto.AnnouncementText);
    announcement.AllDepartmentsBool = ko.observable(announcementDto.AllDepartmentsBool);
    announcement.Editable = ko.observable(false);
    return announcement;
}
var length = viewModel.InitialData.length;
for (i = 0; i < length; i++) {
    var newAnnouncement = createAnnouncement(InitialData[i]);
    viewModel.Announcements.push(newAnnouncement);
}

HTML:

<div id="announcements-container" style="display: inline-block; float: right">
    <ul id="announcements-list" class="newsticker" data-bind="foreach: Announcements">
        <li>
            <span data-bind="html: AnnouncementText"></span>
        </li>
    </ul>
    @Html.Partial("_AnnouncementsModal")
</div>

InitialData从api中按原样填充:


成功了!:

谢谢你的快速回答。我通过用.forEach()迭代数据来获得代码。另一个问题是initialData没有在其当前范围内填充,所以我编辑了getAnnouncements函数,使其工作方式如下:

function getAllAnnouncements() {
    ajaxHelper(announcementsUri, 'GET').done(function(data) {
        data.forEach(function (entry) {
            var newAnnouncement = createAnnouncement(entry);
            self.Announcements.push(newAnnouncement);
        });
    });
};

这一行可能是罪魁祸首:

var length = viewModel.InitialData.length;

请记住,InitialData是一个函数。函数有一个length(这是它们的"arity",即它们具有的形式参数的数量),但可观察数组的length的可观察函数不是数组的length。。

你可能想要里面数组的长度:

var length = viewModel.InitialData().length;
// -------------------------------^^

正如James所指出的,尽管length不起作用,但您对可观测数组上的push的各种调用都起作用,因为Knockout在可观测数组函数上提供了push(以及其他一些东西)。


同样,这一行:

var newAnnouncement = createAnnouncement(InitialData[i]);

可能也想使用该阵列(并且在InitialData前面缺少viewModel.)。

因此,整个部分可能需要进行一点重构:

viewModel.InitialData().forEach(function(entry) {
    var newAnnouncement = createAnnouncement(entry);
    viewModel.Announcements.push(newAnnouncement);
});

或者没有forEach(但实际上,它快到2016年了,在过时的浏览器上可以填充);

var data = viewModel.InitialData();
for (var i = 0; i < data.length; ++i) {
    var newAnnouncement = createAnnouncement(data[i]);
    viewModel.Announcements.push(newAnnouncement);
}

附带说明:您的代码(至少在问题中是这样)也因为没有声明您在for循环中使用的i而成为隐式全局变量的恐怖的牺牲品。我在上面添加了一个var,但这是使用forEach循环遍历数组的另一个原因。

您还可以使用EcmaScript 6样式的枚举,如下所示:

viewModel.InitialData().forEach(item => {
    let newAnnouncement = createAnnouncement(item);
    viewModel.Announcements.push(newAnnouncement);
});