Vue.js - 为按字母顺序排序的列表创建字母 headers
Vue.js - Create letter headers for alphabetically sorted list
我正在迭代以下类型的 JSON object:
"entries": [{
"first_name": "Brigitte",
"last_name": "Bardot",
"country": "Paris, France",
"profession": "Actress"
},
{
"first_name": "Apollo",
"last_name": "AA",
"country": "Witten, Germany",
"profession": "Writer"
}]
使用 v-for 和 lodash 我有一个按字母顺序排列的条目列表:
<div v-for="user in orderedUsers" :key='user' class="user">
<p>{{ user.first_name }} {{ user.last_name }} ({{ user.country }}), {{ user.profession }}</p>
</div>
我想创建一个包含姓氏第一个字母的 header,以便按字母顺序对条目进行分组:
一个
阿波罗
B
芭铎
等..
我用来对条目进行排序的函数如下:
computed: {
orderedUsers: function () {
return orderBy(this.text[0].entries, 'last_name')
}
}
关于实现此目标的简单有效方法有什么想法吗?
按 last_name
对条目进行排序,并按每个用户的第一个字母分组。使用 flatMap 迭代项目,并添加键(姓氏)字母。
在 vue 中使用 v-if
(项目是一个字符串)和 v-else
来决定渲染项目或标题。
const { flow, orderBy, groupBy, flatMap, get } = _
const entries = [{"first_name":"Brigitte","last_name":"Bardot","country":"Paris, France","profession":"Actress"},{"first_name":"Apollo","last_name":"AA","country":"Witten, Germany","profession":"Writer"}]
const groupItems = flow([
arr => orderBy(arr, 'last_name'),
arr => groupBy(arr, o => get(o, 'last_name[0]', '').toUpperCase()),
groups => flatMap(groups, (v, k) => [
k,
...v
])
])
new Vue({
el: '#app',
data: { orderedUsers: groupItems(entries) }
})
/** hide the annoying vue production messages **/
.as-console-wrapper {
display: none !important;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<div id="app">
<div v-for="item in orderedUsers">
<h2 v-if="typeof item === 'string'">
{{ item }}
</h2>
<p v-else>{{ item.first_name }} {{ item.last_name }} ({{ item.country }}), {{ item.profession }}</p>
</div>
</div>
在此期间提出了以下解决方案,但我相信 Ori Dori 的答案更简单。
let users = orderBy(this.text[0].entries, 'last_name');
const map1 = users.map(x => x.last_name.substring(0,1));
const letters = map1.filter(function(item, index){
return map1.indexOf(item) >= index;
});
const groups = {};
// create groups containers from names
letters.forEach(k => {
groups[k] = []
});
users.forEach(k => {
const user = k.last_name.substring(0,1)
groups[user].push(k)
})
return groups
我正在迭代以下类型的 JSON object:
"entries": [{
"first_name": "Brigitte",
"last_name": "Bardot",
"country": "Paris, France",
"profession": "Actress"
},
{
"first_name": "Apollo",
"last_name": "AA",
"country": "Witten, Germany",
"profession": "Writer"
}]
使用 v-for 和 lodash 我有一个按字母顺序排列的条目列表:
<div v-for="user in orderedUsers" :key='user' class="user">
<p>{{ user.first_name }} {{ user.last_name }} ({{ user.country }}), {{ user.profession }}</p>
</div>
我想创建一个包含姓氏第一个字母的 header,以便按字母顺序对条目进行分组:
一个
阿波罗
B
芭铎
等..
我用来对条目进行排序的函数如下:
computed: {
orderedUsers: function () {
return orderBy(this.text[0].entries, 'last_name')
}
}
关于实现此目标的简单有效方法有什么想法吗?
按 last_name
对条目进行排序,并按每个用户的第一个字母分组。使用 flatMap 迭代项目,并添加键(姓氏)字母。
在 vue 中使用 v-if
(项目是一个字符串)和 v-else
来决定渲染项目或标题。
const { flow, orderBy, groupBy, flatMap, get } = _
const entries = [{"first_name":"Brigitte","last_name":"Bardot","country":"Paris, France","profession":"Actress"},{"first_name":"Apollo","last_name":"AA","country":"Witten, Germany","profession":"Writer"}]
const groupItems = flow([
arr => orderBy(arr, 'last_name'),
arr => groupBy(arr, o => get(o, 'last_name[0]', '').toUpperCase()),
groups => flatMap(groups, (v, k) => [
k,
...v
])
])
new Vue({
el: '#app',
data: { orderedUsers: groupItems(entries) }
})
/** hide the annoying vue production messages **/
.as-console-wrapper {
display: none !important;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<div id="app">
<div v-for="item in orderedUsers">
<h2 v-if="typeof item === 'string'">
{{ item }}
</h2>
<p v-else>{{ item.first_name }} {{ item.last_name }} ({{ item.country }}), {{ item.profession }}</p>
</div>
</div>
在此期间提出了以下解决方案,但我相信 Ori Dori 的答案更简单。
let users = orderBy(this.text[0].entries, 'last_name');
const map1 = users.map(x => x.last_name.substring(0,1));
const letters = map1.filter(function(item, index){
return map1.indexOf(item) >= index;
});
const groups = {};
// create groups containers from names
letters.forEach(k => {
groups[k] = []
});
users.forEach(k => {
const user = k.last_name.substring(0,1)
groups[user].push(k)
})
return groups