根据数组中的对象属性生成带有头部的列表

Posted

技术标签:

【中文标题】根据数组中的对象属性生成带有头部的列表【英文标题】:Generate a list with a head based on object property in array 【发布时间】:2019-10-15 13:26:42 【问题描述】:

在 Vue 中,我试图根据对象中的属性生成一个列表。 我有一个来自 vuex 商店的数组,看起来像这样:

const array = [
  
   name: "British title string"
   nationality: "British"
 ,
  
   name: "Another title"
   nationality: "American"
 ,
  
   name: "Name"
   nationality: "Dutch"
 ,
 
   name: "Another american item"
   nationality: "American"
 ,
];

我想要的是使用 v-for 得到这样的输出:

<h2>British</h2>
<ul>
   <li>British title string</li>
</ul>

<h2>American</h2>
<ul>
   <li>Another title</li>
   <li>Another american item</li>
</ul>

<h2>Dutch</h2>
<ul>
   <li>Name</li>
</ul>

我已经使用 lodash _.sortBy 按nationality 属性对数组进行了排序,它给了我一个按国籍排序的数组,但我想添加一个具有国籍值的 H2 元素。

【问题讨论】:

【参考方案1】:

考虑到数组是有序的,你可以这样做:

    const array = [
      
        name: "Another title",
        nationality: "American"
      ,
      
        name: "Another american item",
        nationality: "American"
      ,
      
        name: "British title string",
        nationality: "British"
      ,
      
        name: "Name",
        nationality: "Dutch"
      ,

    ];
    const arrayAux = [];
    var j = 0;
    for (var i = 0; i < array.length;) 
      console.log(array[i].name);
      arrayAux.push(
        nationality: array[i].nationality,
        names: [array[i].name]
      );
      i++;
      while ( i < array.length && array[i].nationality === array[i - 1].nationality) 
        arrayAux[j].names.push(array[i].name);
        i++;
      
      j++;

    
    console.log(arrayAux);

html中:

<div v-for="item in arrayAux">
  <h2> item.nationality </h2>
  <ul>
    <li v-for="n in item.names">
       n.name 
    </li>
  </ul>
</div>

【讨论】:

【参考方案2】:

如果您有多个具有相同国籍的项目并且要将它们分组,请在_.sortBy()之前使用_.groupBy()

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue(
  el: '#app',
  template: '#appTemplate',
  data: () => (
    rawData: [
        name: "British title string",
        nationality: "British"
      ,
      
        name: "Another title",
        nationality: "American"
      ,
      
        name: "Name",
        nationality: "Dutch"
      ,
      
        name: "Another american item",
        nationality: "American"
      
    ]
  ),
  computed: 
    groupedItems() 
      return _.sortBy(
        _.map(
          _.groupBy(this.rawData, 'nationality'), 
          items => (
            items,
            nationality: items[0].nationality
          )
        ), 
        ['nationality']
      );
    
  
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script type="text/template" id="appTemplate">
  <div>
    <template v-for="group in groupedItems">
      <h2 v-text="group.nationality" />
      <ul>
        <li v-for="(item, index) in group.items" :key="index" v-text="item.name" />
      </ul>
    </template>
  </div>
</script>
<div id="app"></div>

为了方便和数据可读性,我将第一个项目的nationality 映射为组的国籍(并将分组的项目命名为items),但您可以直接在模板中使用项目0 的国籍,而不是。 为了演示,下面是它的样子:

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue(
  el: '#app',
  template: '#appTemplate',
  data: () => (
    rawData: [
        name: "British title string",
        nationality: "British"
      ,
      
        name: "Another title",
        nationality: "American"
      ,
      
        name: "Name",
        nationality: "Dutch"
      ,
      
        name: "Another american item",
        nationality: "American"
      
    ]
  ),
  computed: 
    groupedItems() 
      return _.sortBy(
        _.groupBy(this.rawData, 'nationality'), 
        ['0.nationality']
      );
    
  
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script type="text/template" id="appTemplate">
  <div>
    <template v-for="grouped in groupedItems">
      <h2 v-text="grouped[0].nationality" />
      <ul>
        <li v-for="(item, index) in grouped" :key="index" v-text="item.name" />
      </ul>
    </template>
  </div>
</script>
<div id="app"></div>

请注意,以上两个示例都输出了所需的标记。如果您希望每个项目都有自己的包装器,请将 &lt;template&gt; 替换为 html 标记并添加键。即:

<article v-for="(grouped, key) in groupedItems" :key="key">

【讨论】:

如果您还希望在每个组列表中对名称进行排序,请将this.rawData 替换为_.sortBy(this.rawData, 'name')

以上是关于根据数组中的对象属性生成带有头部的列表的主要内容,如果未能解决你的问题,请参考以下文章

根据JavaScript中的属性值从对象数组中选择[重复]

根据自定义对象属性从数组列表中删除元素

根据对象列表生成新卡片

根据对象中的变量对对象的数组列表进行排序

根据属性对不同列表中的对象进行分类

根据对象中的属性添加到列表