一、引言
在开发管理系统时,表格排序是常见需求。本文以自动播报列表为例,介绍在 Vue3 + Element Plus 中如何实现按状态字段排序,让未处理项优先显示。
二、业务场景
在自动播报列表中,需要:
- 未播报(status: 0)优先显示
- 已播报(status: 1)排在后面
- 数据变化时自动重新排序
三、解决方案:使用 Vue3 计算属性
3.1 核心思路
使用 Vue3 的 computed 对原始数据排序,生成排序后的数组供表格使用。这样:
- 响应式:数据变化时自动更新
- 性能:仅依赖变化时重新计算
- 解耦:不修改原始数据
3.2 代码实现
javascript
<script setup lang="ts">
import { computed, reactive } from "vue";
const par = reactive({
tableData: [
{ id: 4276, status: 0, content: '未播报事件1' },
{ id: 4271, status: 0, content: '未播报事件2' },
{ id: 4273, status: 1, content: '已播报事件1' },
{ id: 4274, status: 1, content: '已播报事件2' },
// ... 更多数据
],
// ... 其他属性
});
// 排序后的表格数据:未播报(status: 0)排在已播报(status: 1)前面
const sortedTableData = computed(() => {
return [...par.tableData].sort((a, b) => {
// 按 status 排序:0(未播报)在前,1(已播报)在后
return a.status - b.status;
});
});
</script>
<template>
<el-table
v-loading="par.loading"
:data="sortedTableData"
style="width: 100%"
row-key="id"
>
<!-- 表格列定义 -->
</el-table>
</template>
3.3 关键点解析
- 使用扩展运算符 [...par.tableData]:创建新数组,避免修改原数组
- sort() 比较函数:a.status - b.status 实现升序(0 在前,1 在后)
- computed 响应式:par.tableData 变化时自动重新计算
四、扩展:多条件排序
4.1 多字段排序示例
javascript
const sortedTableData = computed(() => {
return [...par.tableData].sort((a, b) => {
// 第一优先级:按 status 排序(0在前,1在后)
if (a.status !== b.status) {
return a.status - b.status;
}
// 第二优先级:status 相同时,按 level 排序(1>2>3)
if (a.level !== b.level) {
return a.level - b.level;
}
// 第三优先级:按创建时间倒序(最新的在前)
return new Date(b.creationTime).getTime() - new Date(a.creationTime).getTime();
});
});
4.2 可配置排序
javascript
const sortConfig = reactive({
field: 'status', // 排序字段
order: 'asc' // 排序方向:asc 升序,desc 降序
});
const sortedTableData = computed(() => {
return [...par.tableData].sort((a, b) => {
const aVal = a[sortConfig.field];
const bVal = b[sortConfig.field];
if (aVal === bVal) return 0;
const result = aVal > bVal ? 1 : -1;
return sortConfig.order === 'asc' ? result : -result;
});
});
五、Element Plus 表格自带排序功能
5.1 使用 Element Plus 列排序
javascript
<el-table-column
prop="status"
label="播报状态"
sortable
:sort-method="customSort"
>
<!-- 列内容 -->
</el-table-column>
5.2 自定义排序方法
javascript
const customSort = (a, b) => {
// 自定义排序逻辑:0在前,1在后
return a.status - b.status;
};
5.3 两种方案对比
| 特性 | 计算属性排序 | Element Plus 排序 |
|---|---|---|
| 适用场景6 | 全局排序、多条件排序 | 单列排序、用户交互排序 |
| 性能 | 数据量大时需注意 | 内置优化 |
| 灵活性 | 高 | 中等 |
| 用户体验 | 自动排序 | 用户可控制 |
六、性能优化建议
6.1 大数据量优化
javascript
// 使用防抖,避免频繁排序
import { debounce } from 'lodash-es';
const sortedTableData = computed(() => {
// 如果数据量很大,可以考虑分页后再排序
if (par.tableData.length > 1000) {
// 先分页,再排序
const pageData = par.tableData.slice(
(par.page - 1) * par.limit,
par.page * par.limit
);
return pageData.sort((a, b) => a.status - b.status);
}
return [...par.tableData].sort((a, b) => a.status - b.status);
});
6.2 使用 Web Worker(超大数据量)
javascript
// worker.js
self.onmessage = function(e) {
const { data } = e.data;
const sorted = [...data].sort((a, b) => a.status - b.status);
self.postMessage(sorted);
};
// 组件中
const sortedTableData = ref([]);
const sortInWorker = (data) => {
const worker = new Worker('/worker.js');
worker.postMessage({ data });
worker.onmessage = (e) => {
sortedTableData.value = e.data;
worker.terminate();
};
};
七、常见排序场景
7.1 数字排序
javascript
return a.number - b.number; // 升序
return b.number - a.number; // 降序
7.2 字符串排序
javascript
return a.name.localeCompare(b.name); // 中文排序
return a.name > b.name ? 1 : -1; // 简单排序
7.3 日期排序
javascript
return new Date(a.date).getTime() - new Date(b.date).getTime();
八、完整示例代码
javascript
<template>
<div class="broadcast-list">
<el-table
v-loading="par.loading"
:data="sortedTableData"
style="width: 100%"
row-key="id"
@row-click="handleRowClick"
>
<el-table-column prop="id" label="事件编号" />
<el-table-column prop="type" label="事件类型" />
<el-table-column prop="content" label="事件内容" />
<el-table-column label="播报状态">
<template #default="scope">
<span v-if="scope.row.status === 0">未播报</span>
<span v-else>已播报</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { computed, reactive } from "vue";
const par = reactive({
loading: false,
tableData: [] as any[],
});
// 排序后的表格数据
const sortedTableData = computed(() => {
return [...par.tableData].sort((a, b) => {
// 未播报(0)在前,已播报(1)在后
return a.status - b.status;
});
});
const handleRowClick = (row: any) => {
console.log('点击行:', row);
};
</script>
九、总结
- 使用 computed 实现响应式排序,代码简洁
- 通过扩展运算符避免修改原数组
- 多条件排序时按优先级依次比较
- 大数据量时考虑分页或 Web Worker
- 根据场景选择计算属性排序或 Element Plus 列排序
创作不易,如果对你有帮助的话可以评论留言或者点赞收藏+关注哦