【问题标题】: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 元素。

【问题讨论】:

    标签: javascript arrays vue.js lodash


    【解决方案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')
      猜你喜欢
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      • 2019-04-23
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多