В 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 со значением национальности.
Вы можете сделать это, учитывая, что массив упорядочен:
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')
.