按照键值分组列出数组内容

7

如果我的术语不正确,我很抱歉——这绝对不是我的专业领域。

我想从一个json文件中制作一个<select>列表,并通过一个键将条目分组在<optgroup>中。 我已经成功地能够列出选择中的所有条目,但不知道如何循环并将项目嵌套在其键下。

我的JSON长这样:

[
    {
        "Type" : "Overdrive",
        "Brand" : "Chase Bliss",
        "Name" : "Brothers",
        "Width" : 2.75,
        "Height" : 4.77,
        "Image" : "public/images/pedals/chasebliss-brothers.png"
    }
]

以下是我如何渲染 <select>

window.RenderPedals = function(pedals){
    for(var i in pedals) {
        var $pedal = $("<option>"+ pedals[i].Brand + " " + pedals[i].Name +"</option>").attr('id', pedals[i].Name.toLowerCase().replace(/\s+/g, "-").replace(/'/g, ''));
        $pedal.data('width', pedals[i].Width);
        $pedal.data('height', pedals[i].Height);
        $pedal.data('height', pedals[i].Height);
        $pedal.data('image', pedals[i].Image);
        $pedal.appendTo('.pedal-list');
    }
}

我所需要的是这个标记:
<select>
    <optgroup label="Chase Bliss">
        <option data-width="..." data-height="..." data-image="...">Chase Bliss Brothers</option>
    </optgroup>
</select>

有人能给我指条明路吗?


1
如果pedals是一个数组,你应该看一下这个问题及其答案 - Heretic Monkey
2个回答

0

您可以使用对象解构获取当前对象的属性,而无需使用for..in循环,创建一个<optgroup>元素,并将label属性设置为"Brand",将<option>附加到<optgroup>,将<optgroup>附加到<select>。检查是否存在一个<optgroup>元素,其label属性设置为Brand,如果是true,则将<option>附加到该<optgroup>,否则将一个新的<optgroup>元素附加到<select>中,并将html设置为新的<option>元素。

var data = [{
  "Type": "Overdrive",
  "Brand": "Chase Bliss",
  "Name": "Brothers",
  "Width": 2.75,
  "Height": 4.77,
  "Image": "public/images/pedals/chasebliss-brothers.png"
}
, {
  "Type": "Underdrive",
  "Brand": "Bliss Chase",
  "Name": "Sisters",
  "Width": 5.72,
  "Height": 7.74,
  "Image": "public/images/pedals/chasebliss-sisters.png"
 }
 , {
  "Type": "Throughdrive",
  "Brand": "Bliss Chase",
  "Name": "Cousins",
  "Width": 2.75,
  "Height": 4.74,
  "Image": "public/images/pedals/chasebliss-cousins.png"
 }
];

window.RenderPedals = function(pedals) {
  var {Type, Brand, Name, Width, Height, Image} = pedals;
  var option = $("<option>", {
                 text: `${Brand} ${Name}`,
                 id: Name.toLowerCase()
                     .replace(/(\s+)|(['"])/g, (m, p1, p2) => p1 ? "-" : ""),
                 data: {
                   width: Width,
                   height: Height,
                   image: Image
                 }
               });
  if ($("optgroup").is(`[label="${Brand}"]`)) {
    $(`optgroup[label="${Brand}"]`).append(option);
  } else {
    $("<optgroup>", {
      label: Brand,
      html: option
    }).appendTo(".pedal-list");
  }
}

data.forEach(RenderPedals);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<select class="pedal-list"></select>


这样不会错过“分组”部分吗?即数组中的所有条目都将列在第一个品牌下。 - bsyk
@bsyk 不确定你的意思?问题中只有一个对象出现在数组中。OP可以使用data.forEach(RenderPedals) - guest271314
我假设问题中的数据被简化为单个条目,并且在实际应用程序中会有更多的条目,否则分组列表框的意义何在。 尝试添加具有不同品牌值的更多条目到您的数组中。 - bsyk
可能是新手问题,但我的编译器似乎不想编译这个语法。有没有另一种不使用反引号的写法? - Travis L
1
@guest271314 找到了卡住的 gulp 插件 - 现在完美运行。再次感谢! - Travis L
显示剩余2条评论

0
如果您有一个与HTML匹配的数据结构,那么推理就会变得更加容易。
给定
[
    {
        "Type" : "Overdrive",
        "Brand" : "Chase Bliss",
        "Name" : "Brothers",
        "Width" : 2.75,
        "Height" : 4.77,
        "Image" : "public/images/pedals/chasebliss-brothers.png"
    }
]

当你需要这个结构时

<select>
    <optgroup label="Chase Bliss">
        <option data-width="..." data-height="..." data-image="...">Chase Bliss Brothers</option>
    </optgroup>
</select>

不要试图将JSON转换为HTML,而是创建一个与HTML匹配的新数据结构。如果数据结构与HTML结构匹配,呈现它的逻辑会更容易。

以下类似的结构将非常有效:

[
  {
    brandName: "Chase Bliss",
    items: [ { name: "Brothers" /* width, height, etc */ } ]
  }
]

你可以编写一个reduce函数来进行这个转换:
let optionGroups = pedals.reduce((optionGroups, pedal) => { 
  let optionGroup = optionGroups.find(group => pedal.Brand === group.brandName) || {}

  if (!optionGroup.brandName) {
    optionGroup.brandName = pedal.Brand
    optionGroup.items = []
    optionGroups.push(optionGroup)
  }

  optionGroup.items.push(pedal)
  return optionGroups
}, [])

渲染函数可以先映射外部组,然后再映射内部项。

window.renderPedals = (optionGroups) => {
  optionGroups.map((group) => {
    let $optgroup = $("<optgroup>", {
      label: group.brandName
    });

    group.items.map((pedal) => {
      let {Type, Brand, Name, Width, Height, Image} = pedal;
      let $pedal = $("<option>", {
        text: `${Brand} ${Name}`,
        id: `${Name.toLowerCase().replace(/\s+/g, "-").replace(/'/g, '')}`,
        data: {
          width: Width,
          height: Height,
          image: Image
        },
        appendTo: $optgroup
      });
    })
    $optgroup.appendTo(".pedal-list");
  })
}

https://jsfiddle.net/f4x9vk0f/2/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接