Javascript Vue 3/Vuex:在前端对二维数组进行排序
我有一个表布局,其中有一个“聊天”列表。我的方法是让一个组件将“chat”属性传递给一个组件,该组件将为每个chat行组成TR。因此,ChatList组件从Vuex带来chats数组,然后将“chat”属性传递给构建表的TBODY的chat组件。我还根据THEAD(即ChatList组件)上的每一列对表进行过滤,因为我使用了计算值和方法的组合。当我访问来自一维数组的信息时,排序工作得很好,问题是当我尝试对二维数组执行相同的操作时,我只是不知道如何对数组中更深入的对象进行排序以显示数据,同时从表列触发排序 ChatList组件模板:包括一个筛选器部分,我在其中使用输入来筛选表(这仅适用于“chat.startedAt”,但在我尝试访问“chat.timeInQueue.minutes”等属性时不起作用):Javascript Vue 3/Vuex:在前端对二维数组进行排序,javascript,vue.js,vuex,Javascript,Vue.js,Vuex,我有一个表布局,其中有一个“聊天”列表。我的方法是让一个组件将“chat”属性传递给一个组件,该组件将为每个chat行组成TR。因此,ChatList组件从Vuex带来chats数组,然后将“chat”属性传递给构建表的TBODY的chat组件。我还根据THEAD(即ChatList组件)上的每一列对表进行过滤,因为我使用了计算值和方法的组合。当我访问来自一维数组的信息时,排序工作得很好,问题是当我尝试对二维数组执行相同的操作时,我只是不知道如何对数组中更深入的对象进行排序以显示数据,同时从表列
聊天
电子邮件
开始于
排队时间
地位
优先
名称
部门
标签
客户
烙印
语言
从“vuex”导入{mapState};
从“@/components/Icons/IconBase.vue”导入IconBase;
从“@/components/Icons/IconAsc.vue”导入IconAsc;
从“@/components/Icons/IconDesc.vue”导入IconDesc;
从“@/components/Chat.vue”导入聊天;
导出默认值{
组成部分:{
聊天,
IconBase,
IconAsc,
IconDesc
},
创建(){
此.$store.dispatch(“chat/fetchChats”);
},
数据(){
返回{
当前排序:“电子邮件”,
currentSortDir:“asc”
};
},
计算:{
…地图状态({
chats:state=>state.chat.chats
}),
分类帽子(){
返回此.chats.slice().sort((a,b)=>{
设修饰符=1;
如果(this.currentSortDir==“desc”)修饰符=-1;
if(a[this.currentSort]b[this.currentSort])返回1*修饰符;
返回0;
});
}
},
方法:{
排序(列排序){
if(columnToSort==this.currentSort){
this.currentSortDir=this.currentSortDir===“asc”?“desc”:“asc”;
}
this.currentSort=columnToSort;
}
}
};
聊天组件-构建表体,我不知道如何对需要显示二维数组中数据的列进行排序。我需要按chat.visitor.email之类的内容进行排序(visitor是chats数组中的一个数组)
{{chat.visitor.email}
{{chat.startedAt}}
{{chat.timeInQueue.minutes}
{{chat.status}
{{chat.priority}}
{{chat.visitor.name}
{{chat.visitor.departmentName}
{{
标签
}}
{{chat.visitor.client}
{{chat.visitor.brand}
{{chat.visitor.language}
导出默认值{
//eslint禁用下一行vue/需要道具类型
道具:[“聊天”],
计算:{}
};
<template>
<div>
<h1 class="text-center font-semibold">Chats</h1>
<div class="px-4 mt-6">
<table class="text-left w-full">
<thead>
<tr>
<th class="px-4 py-2" @click="sort('email')">
<div
class="bg-gray-300 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<span>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="asc"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="desc"
><IconDesc
/></IconBase>
</span>
<span>Email</span>
</div>
</th>
<th class="px-4 py-2" @click="sort('startedAt')">
<div
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<span>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="asc"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="desc"
><IconDesc
/></IconBase>
</span>
<span>Started At</span>
</div>
</th>
<th class="px-4 py-2" @click="sort('timeInQueue')">
<div
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<span>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
</span>
<span>Time In Queue</span>
</div>
</th>
<th class="px-4 py-2" @click="sort('status')">
<div
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<span>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
</span>
<span>Status</span>
</div>
</th>
<th class="px-4 py-2" @click="sort('priority')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Priority</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('name')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Name</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('department')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Department</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('tags')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Tags</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('client')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Client</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('brand')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Brand</span>
</button>
</th>
<th class="px-4 py-2" @click="sort('language')">
<button
class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center"
>
<IconBase
v-if="currentSortDir === 'asc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconAsc
/></IconBase>
<IconBase
v-if="currentSortDir === 'desc'"
class="fill-current w-4 h-4 mr-2"
icon-color="rgba(0,0,0,0.80)"
icon-name="checkmark"
><IconDesc
/></IconBase>
<span>Language</span>
</button>
</th>
</tr>
</thead>
<tbody>
<Chat
v-for="(chat, index) in sortedChats"
:key="index"
:chat="chat"
:data-index="index"
></Chat>
</tbody>
</table>
</div>
</div>
</template>
<script>
import { mapState } from "vuex";
import IconBase from "@/components/Icons/IconBase.vue";
import IconAsc from "@/components/Icons/IconAsc.vue";
import IconDesc from "@/components/Icons/IconDesc.vue";
import Chat from "@/components/Chat.vue";
export default {
components: {
Chat,
IconBase,
IconAsc,
IconDesc
},
created() {
this.$store.dispatch("chat/fetchChats");
},
data() {
return {
currentSort: "email",
currentSortDir: "asc"
};
},
computed: {
...mapState({
chats: state => state.chat.chats
}),
sortedChats() {
return this.chats.slice().sort((a, b) => {
let modifier = 1;
if (this.currentSortDir === "desc") modifier = -1;
if (a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if (a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;
});
}
},
methods: {
sort(columnToSort) {
if (columnToSort === this.currentSort) {
this.currentSortDir = this.currentSortDir === "asc" ? "desc" : "asc";
}
this.currentSort = columnToSort;
}
}
};
</script>
<template>
<tr>
<td class="px-4 py-2">
{{ chat.visitor.email }}
</td>
<td class="px-4 py-2">
{{ chat.startedAt }}
</td>
<td class="px-4 py-2">
{{ chat.timeInQueue.minutes }}
</td>
<td class="px-4 py-2">
{{ chat.status }}
</td>
<td class="px-4 py-2">
{{ chat.priority }}
</td>
<td class="px-4 py-2">
{{ chat.visitor.name }}
</td>
<td class="px-4 py-2">
{{ chat.visitor.departmentName }}
</td>
<td class="px-4 py-2">
<span v-for="(tag, index) in chat.visitor.tags" :key="index">{{
tag
}}</span>
</td>
<td class="px-4 py-2">
{{ chat.visitor.client }}
</td>
<td class="px-4 py-2">
{{ chat.visitor.brand }}
</td>
<td class="px-4 py-2">
{{ chat.visitor.language }}
</td>
</tr>
</template>
<script>
export default {
// eslint-disable-next-line vue/require-prop-types
props: ["chat"],
computed: {}
};
</script>