简体   繁体   English

映射和绑定嵌套对象和数组

[英]Mapping and binding nested objects and arrays

I have an object and within this object I have items and one of the items is an array which also contains objects . 我有一个object ,在这个对象中我有一个项目,其中一个项目是一个也包含objectsarray A sample of the data is shown below. 数据示例如下所示。

I am using knockout to bind this data to the view so I think I need to implement a double loop for returning the objects and the objects within the child array to be able to bind them in the view. 我正在使用敲除法将此数据绑定到视图,所以我想我需要实现一个双循环以返回对象和子数组中的对象,以便能够将它们绑定到视图中。

Sample data: 样本数据:

"singers": {
        "ijiyt6ih": {
            "id": ObjectId('ijiyt6ih'),
            "name": "John",
            "songs": [
                {
                    "id": ObjectId('okoiu8yi'),
                    "songName": "Hello There",
                    "year": "1980"
                },
                {
                    "id": ObjectId('sewfd323'),
                    "songName": "No More",
                    "year": "1983"
                }
            ]
        },
        "98usd96w": {
            "id": ObjectId('98usd96w'),
            "name": "Jack",
            "songs": [
                {
                    "id": ObjectId('iew342o3'),
                    "songName": "Hurry Up",
                    "year": "1985"
                }
            ]
        }
    }

I need to find a way to appropriately loop through this so that I can modify the returned data to bind it to the viewModel using knockout. 我需要找到一种方法来适当地遍历此过程,以便可以修改删除的数据,以便使用敲除将其绑定到viewModel。

Here is how my viewModel looks like: 这是我的viewModel的样子:

singersViewModel = function(data) {
   var self = {
           singerId: ko.observable(data.id),
           singerName: ko.observable(data.name),
           songName: ko.observable(...),
           songYear: ko.observable(...)
       };

I am not sure if I will have to return two different sets of data or not. 我不确定是否必须返回两组不同的数据。

As for the looping. 至于循环。 I was able to loop and return the list of singers to display on the page but I am not able to get the list of songs displayed within each singer. 我能够循环播放并返回要在页面上显示的歌手列表,但无法获取每个歌手中显示的歌曲列表。

Here is my loop so far: 到目前为止,这是我的循环:

var self = {},
    singer,
    tempSingers = [];

    self.singers = ko.observableArray([]);
    for (singer in singers) {
        if (singers.hasOwnProperty(singer)) {
             tempSingers.push(new singersViewModel(singers[singer]));
           }
     }
     self.singers(tempSingers);

I tried to duplicate the same type of loop for songs within this loop but i would get an error using hasOwnProperty because songs is an array . 我尝试在此循环中为歌曲复制相同类型的循环,但是使用hasOwnProperty会出错,因为歌曲是一个array

In the included snippet you can see how you can map the original data to a viewmodel that can be bound to a view. 在随附的代码段中,您可以看到如何将原始数据映射到可以绑定到视图的视图模型。

I've left the ids as regular properties, and converted the names into observables, so thatthey can be edited. 我将id保留为常规属性,并将名称转换为可观察的名称,以便可以对其进行编辑。 At the bottom you can see the current viewmodel state. 在底部,您可以看到当前视图模型的状态。

There is also a sample view which iterates the list of singers, and also the list of song within each singer. 还有一个示例视图,该视图可迭代歌手列表以及每个歌手中的歌曲列表。

As you can see I'm implementing the solution using mapping. 如您所见,我正在使用映射实现解决方案。 For mapping you need to implement a callback that receives each original object and returns a new one with a new structure. 对于映射,您需要实现一个回调,该回调可接收每个原始对象并返回具有新结构的新对象。 For example this part of the code 例如这部分代码

_.map(_singers, function(singer) {
    return {
      id: singer.id,
      name: ko.observable(singer.name),
      // ... songs: 
})

iterates over each singer (the sample data in the question), and for each one creates a new object with the id, an observable which includes the name (and the mapping of songs, which I don't show in this fragment). 遍历每位歌手(问题中的示例数据),并为每位歌手创建一个具有ID的新对象,该对象具有可观察性,其中包括名称(以及歌曲的映射,在此片段中未显示)。

NOTE: I'm using lodash , but many browsers support map natively as an array function 注意:我使用lodash ,但是许多浏览器都将map作为数组函数本地支持

 var ObjectId = function (id) { return id; } var singers = { "ijiyt6ih": { "id": ObjectId('ijiyt6ih'), "name": "John", "songs": [ { "id": ObjectId('okoiu8yi'), "songName": "Hello There", "year": "1980" }, { "id": ObjectId('sewfd323'), "songName": "No More", "year": "1983" } ] }, "98usd96w": { "id": ObjectId('98usd96w'), "name": "Jack", "songs": [ { "id": ObjectId('iew342o3'), "songName": "Hurry Up", "year": "1985" } ] } }; var SingersVm = function(_singers) { var self = this; self.singers = _.map(_singers, function(singer) { return { id: singer.id, name: ko.observable(singer.name), songs: _.map(singer.songs, function(song) { return { name: ko.observable(song.songName), id: song.id }; }) }; }); return self; }; var vm = new SingersVm(singers); //console.log(vm); ko.applyBindings(vm); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div data-bind="foreach: singers"> <div> <input data-bind="value: name"/> (<span data-bind="text: id"></span>) <ul data-bind="foreach:songs"> <li> <input data-bind="value: name"/> (<span data-bind="text: id"></span>) </li> </ul> </div> </div> <pre data-bind="html: ko.toJSON($root,null,2)"> </pre> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM