Создайте список с заголовком на основе свойства объекта в массиве

В 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>

Я уже отсортировал массив по свойству nationality, используя lodash _.sortBy, и он дал мне массив, отсортированный по национальности, но я хочу добавить элемент H2 со значением национальности.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
45
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете сделать это, учитывая, что массив упорядочен:

    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.info(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.info(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>
Ответ принят как подходящий

Если у вас есть несколько предметов одной национальности и вы хотите их сгруппировать, используйте _.groupBy() перед _.sortBy():

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>

Обратите внимание, что оба приведенных выше примера выводят требуемую разметку. Если вы хотите, чтобы у каждого элемента была своя оболочка, замените <template> тегом html и добавьте ключи. то есть:

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

Если вы также хотите, чтобы имена сортировались внутри каждого списка групп, замените this.rawData на _.sortBy(this.rawData, 'name').

tao 30.05.2019 13:18

Другие вопросы по теме