vue3 + antd二次封装a-table组件

前置条件

vue版本 v3.3.11
ant-design-vue版本 v4.1.1

内容梗概

二次封装a-table组件,大大提高工作效率和降低项目维护成本;

先看效果图

在这里插入图片描述

代码区域

utils.js文件

// 用于模拟接口请求
export const getRemoteTableData = (data = [], time = 1000) => {return new Promise((resolve) => {setTimeout(() => {const retObj = {list: data,total: 100,pageSize: 10,pageNum: 1,}resolve(retObj)}, time)})
}// 指定范围随机数
export const getRandomNumber = (min, max) => {return Math.floor(Math.random() * (max - min + 1) + min);
}// 判断空值
export const isEmpty = (value) => {if (Array.isArray(value)) {return !value.length} else if (Object.prototype.toString.call(value) === "[object Object]") {return !Object.keys(value).length} else {return [null, undefined, ''].includes(value)}
}//  数字格式化
export const formatNumber = (num) =>num ? (num + "").replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, "$&,") : (isEmpty(num) ? '' : 0)// 百分比格式化
export const formatPercent = (percent, n = 2) => isEmpty(percent) ? '' : `${(+percent).toFixed(n)}%`// 金额格式化
export const formatMoney = (num) => isEmpty(num) ? "" : formatNumber(num.toFixed(2))

my-table.vue组件

<template><div><div class="attach-buttons-wrap"><a-buttonstyle="margin-right: 10px"v-bind="btn.props"@click="btn.onclick({ selectedRowKeys })"v-for="btn in attachButtons":key="btn.name":disabled="typeof btn?.props?.disabled === 'function'? btn?.props?.disabled(selectedRowKeys): btn?.props?.disabled ?? false">{{ btn.name }}</a-button></div><a-tablev-bind="{loading: localLoading,pagination: localPagination,rowSelection: localRowSelection,rowKey: 'id',...$attrs,}":dataSource="dataSource"><!-- 自定义渲染单元格 --><template #bodyCell="{ text, record, index, column }"><!-- 操作列 --><template v-if="column.dataIndex === 'operation'"><av-for="(item, itemIndex) in column.buttons":key="itemIndex"@click="item.onclick({ text, record, index, column })":style="{marginRight: '12px',display: btnShow({ item, text, record, index, column })? 'inline-block': 'none',...(item.style || {}),}">{{ item.name }}</a></template><!-- 序号 --><template v-if="column.type === 'serial'">{{(localPagination.current - 1) * localPagination.pageSize + index + 1}}</template><!-- 百分比 --><template v-else-if="column.type === 'percent'">{{formatPercent(text)}}</template><!-- 数值 --><template v-else-if="column.type === 'number'">{{formatNumber(text)}}</template><!-- 金额 --><template v-else-if="column.type === 'money'">{{formatMoney(text)}}</template><!-- 列插槽 --><template v-else-if="columnSlots.includes(column.dataIndex)"><template v-for="slot in columnSlots" :key="slot"><slot:name="`column-${slot}`"v-bind="{ text, record, index, column }"></slot></template></template><!-- 自定义列渲染 --><template v-else-if="typeof column?.customRender === 'function'"><!-- 渲染customRender --><component:is="column.customRender"v-bind="{ text, record, index, column }"></component></template></template><!-- 插槽透传 --><template v-for="(value, name) in $slots" v-slot:[name]="slotProps"><slot :name="name" v-bind="slotProps"></slot></template></a-table></div>
</template><script setup>
import { ref, reactive, computed, onMounted, useSlots, unref } from "vue";
import { formatPercent, formatMoney, formatNumber } from "@/common/utils";
const props = defineProps({data: {type: [Function, Array],default: () => [],},// 附属操作按钮attachButtons: {type: Array,default: () => [],},
});
const emits = defineEmits(["refresh"]);
const slots = useSlots();
const columnSlots = ref([]);
const createColumnSlots = () => {columnSlots.value = Object.keys(slots).filter((x) => x.indexOf("column") !== -1).map((x) => x.split("-")[1]);
};const btnShow = computed(() =>({ item, text, record, index, column }) =>typeof item?.show == "function"? item.show({ text, record, index, column }): item.show ?? true
);
// 列表数据
const dataSource = ref([]);
// 分页
const localPagination = reactive({current: 1,pageSize: 10,total: 0,showTotal: (total) => `${total} 条记录`,showSizeChanger: true,showQuickJumper: true,onChange: (current, size) => {localPagination.current = current;localPagination.pageSize = size;loadData({ current, pageSize: size });},pageSizeOptions: ["10", "20", "30", "40", "50"],
});
// 是否分页
const isPagination = ref(false);
// loading状态
const localLoading = ref(false);
const selectedRowKeys = ref([]);
// 选择列
const onSelectChange = (rowKeys) => {selectedRowKeys.value = rowKeys;
};
const localRowSelection = computed(() => {return {selectedRowKeys: unref(selectedRowKeys),onChange: onSelectChange,};
});const loadData = (pagination) => {localLoading.value = true;const params = isPagination.value? {pageNo: pagination?.current? pagination.current: localPagination.current,pageSize: pagination?.pageSize? pagination.pageSize: localPagination.pageSize,}: {};if (!props.data) {dataSource.value = [];return;}if (Array.isArray(props.data)) {dataSource.value = props.data;localLoading.value = false;} else {props.data(params).then((retObj) => {const { list, total, pageSize, pageNum } = retObj;isPagination.value = retObj.hasOwnProperty("list");if (isPagination.value) {localPagination.total = total || 0;localPagination.pageSize = pageSize;localPagination.pageNum = pageNum;dataSource.value = list?.length ? list : [];if (list?.length === 0 && localPagination.current > 1) {localPagination.current--;loadData();}} else {dataSource.value = retObj?.length ? retObj : [];}}).finally(() => (localLoading.value = false));}
};// 刷新表格数据
const refresh = (isInit = false) => {// 页码重置1if (isInit) {localPagination.current = 1;localPagination.total = 0;emits("refresh");}loadData();
};onMounted(() => {createColumnSlots();loadData();
});defineExpose({ refresh });
</script><style lang="scss" scoped>
.attach-buttons-wrap {margin-bottom: 10px;
}
</style>

使用该组件

<template><div style="padding: 40px"><MyTableref="myTable":data="getDataFromApi":columns="columns":attachButtons="attachButtons"><template #column-tags="{ record }"><a-tag v-for="tag in record.tags" :key="tag">{{ tag.toUpperCase() }}</a-tag></template><template #headerCell="{ column }"><template v-if="column.dataIndex === 'tags'">测试表头(列插槽)</template></template></MyTable></div>
</template><script lang="jsx" setup>
import MyTable from "@/components/table/index.vue";
import { ref } from "vue";import { getRemoteTableData, getRandomNumber } from "@/common/utils";
const myTable = ref(null);const columns = [{title: "序号",dataIndex: "name",type: "serial",},{title: "姓名",dataIndex: "name",},{title: "年龄",dataIndex: "age",},{title: "性别",dataIndex: "sex",},{title: "士兵数量",dataIndex: "score",type: "number",},{title: "铁骑兵占比",dataIndex: "percent",type: "percent",},{title: "军费",dataIndex: "price",type: "money",},{title: "标签",dataIndex: "tags",},{title: "自定义渲染列",dataIndex: "custom",customRender: ({record}) => <div><a>{record.name} </a><span style="color: green">年龄:{record.age}</span></div>},{title: "操作",dataIndex: "operation",buttons: [{name: "查看",onclick: ({ record }) => {console.log("查看", record);},show: ({ record }) => record.name === "诸葛亮4",},{name: "编辑",onclick: ({ record }) => {console.log("编辑", record);},},{name: "删除",onclick: ({ record }) => {console.log("删除", record);},style: {color: "red",},},],width: 180,},
];const getDataFromApi = async () => {let getData = Array.from({ length: 10 }, (_, i) => i).map((x, i) => ({id: getRandomNumber(1, 10000000000000),name: `诸葛亮${i + 1}`,age: getRandomNumber(10, 100),sex: ``,price: getRandomNumber(1000, 100000),percent: getRandomNumber(1, 100),score: getRandomNumber(100000, 1000000000),tags: ["OK", "YES"],}));return await getRemoteTableData([...getData]);
};const attachButtons = ref([{name: "刷新",onclick: () => myTable.value.refresh(true)},{name: "批量删除",onclick: ({selectedRowKeys}) => {console.log('selectedRowKeys', selectedRowKeys)},props: {type: 'primary',danger: true,disabled: (selectedRowKeys) => !selectedRowKeys.length}},{name: "导出Excel",onclick: () => {console.log('导出文件')},props: {type: 'primary',},}
])
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/535220.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的输电线路设备检测系统(深度学习+UI界面+Python代码+训练数据集)

摘要&#xff1a;本篇博客详细介绍了如何运用深度学习构建一个先进的输电线路设备检测系统&#xff0c;并附上了完整的实现代码。该系统利用了最新的YOLOv8算法作为其核心&#xff0c;同时也对之前版本的YOLOv7、YOLOv6、YOLOv5进行了性能比较&#xff0c;包括但不限于mAP&…

代码随想录算法训练营第六天| 242.有效字母的异位词、349.两个数组的交集、202快乐数、1.两数之和

系列文章目录 目录 系列文章目录242.有效的字母异位词349. 两个数组的交集①使用HashSet②使用Hash数组 202. 快乐数1. 两数之和①暴力解法&#xff08;时间复杂度不符合要求&#xff09;②使用HashMap法 242.有效的字母异位词 这道题是数组在哈希表中的典型应用。 因为只有2…

Frostmourne - Elasticsearch源日志告警配置

简介 配置Frostmourne 接入Elasticsearch源进行日志匹配告警&#xff0c;并静默规则&#xff0c;告警消息发送到企业微信&#xff0c;告警信息使用Markdown。 部署安装教程查看&#xff1a; https://songxwn.com/frostmourne_install ELK 安装教程&#xff1a;https://songx…

【Python】新手入门学习:详细介绍开放封闭原则(OCP)及其作用、代码示例

【Python】新手入门学习&#xff1a;详细介绍开放封闭原则&#xff08;OCP&#xff09;及其作用、代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyT…

【Linux】进程控制与进程调度

Linux进程介绍 进程的基本概念 Linux是多用户、多任务的操作系统。在这样的环境中&#xff0c;各种计算机资源的分配和管理都是以进程为单位进行的。 Linux操作系统包括三种不同类型的进程&#xff1a; 1&#xff09;交互进程&#xff1a;一种由Shell启动的进程。交互进程既可…

车辆监控系统:AI赋能黑科技,砼车监管有哨兵!

或许您也有兴趣看看这些&#xff1a; 超级调度 | 砼行ERP 搅拌站运转效率提高30% 生产控制 | 一机双控 省钱 省事 增收 智能地磅 | 自助过磅 料仓联动 自助卸料 管理系统 | 混凝土 用砼行 协同管理 | 智能制造 生产协同 ↓添加下方好友&#xff0c;获取更详细的资料

Windows从0到1部署项目

文章目录 1.创建虚拟机2.文件的传输--共享文件夹共享文件夹的访问 3.安装jdk&#xff0c;Tomcat3.1jdk的安装与配置配置环境变量 3.2Tomcat的安装与配置 4.安装mysql数据库5.下载nginx6.虚拟域名 因为Windows项目部署有很多操作都是博主之前做过的了&#xff0c;所及就只放了博…

Failed to open file:login.html段错误,核心已转储

目录 关于段错误 1.错误想象如下所示 2.相应代码 3.原因分析 4.段错误处理原则 关于段错误 "段错误"是一种常见的运行时错误&#xff0c;通常表示程序访问了无效的内存地址&#xff0c;导致操作系统终止了程序的执行并生成了核心转储文件。出现段错误的原因可能…

【漏洞复现】宏景HCM downlawbase SQL注入漏洞

0x01 产品简介 宏景人力资源管理软件是一款人力资源管理与数字化应用相融合&#xff0c;满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景HCM downlawbase 接口处存在SQL注入漏洞&#xff0c;未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令&…

DJI RONIN 4D变0字节恢复案例

RONIN 4D这个产品听起来比较陌生&#xff0c;还是DJI大疆出品。没错&#xff0c;这是大疆进军影视级的重点明星机型。前阵子刚处理过大疆RONIN 4D的修复案例&#xff0c;下边这个案例是和exfat有关的老问题:文件长度变成0字节。 故障存储:希捷18T /MS Exfat文件系统。 故障现…

vue.js 页面中设置多个swiper

效果&#xff1a; 设置主要设置了 动态的 包含类、 左右按钮的类 <template><div class"swiper-container_other"><!-- 右侧按钮 --><div :class"[(id)?swiper-button-nextid:swiper-button-next, swiper-button-next]"></div…

【代码随想录 | 数组 01】二分查找

文章目录 1.二分查找1.1题目1.2思路&#xff08;核心&#xff1a;区间的定义&#xff09;1.3左闭右闭1.4左闭右开1.5总结 1.二分查找 1.1题目 704.二分查找—力扣题目链接 题目&#xff1a;给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 …