vue3+elementplus基于el-table-v2封装公用table组件详细代码
作者:_Jyann_
在日常开发后端管理系统项目中,用于展示数据多会用表格进行展示,下面这篇文章主要给大家介绍了关于vue3+elementplus基于el-table-v2封装公用table组件的相关资料,需要的朋友可以参考下
1.梳理出需要封装的功能
主要是针对表格进行封装,不包括查询表单和操作按钮。
梳理出系统中通用表格的功能项,即表格主体的所有功能,生成columns列头数据、生成data表体数据、拖拉列宽、分页、生成中文列名、自定义列宽width
效果如下:
2.封装表格(表格+分页)
<template> <slot></slot> <div class="table-v2"> <el-auto-resizer always height="36"> <!--行高 :row-height="36" --> <template #default="{ height, width }"> <el-table-v2 :columns="columns" :scrollbar-always-on="true" :data="data" :width="width" :height="height" :row-height="36" :row-key="data.id" fixed> </el-table-v2> </template> </el-auto-resizer> <!-- 分页 --> <div class="pagination" v-if="showPage"> <el-pagination background class="pagination" layout="prev, pager, next" :current-page="pageNum" :total="total" :page-size="pageSize" @prev-click="prevClick" @next-click="nextClick" @current-change="currentChange" /> </div> </div> </template>
父级引用:
<!-- 表格 --> <t-table-v2 @handle-pagenation="handlePagenation"></t-table-v2>
3.将生成列名和表体数据、复选框、操作按钮等方法封装成类
import { unref } from 'vue' import { ElCheckbox, TableV2FixedDir } from 'element-plus' export default class GenerateTableData { // options: {columns:...,data:...} constructor(data) { this.data = data; this.column = this.createColumnsData(); this.rowData = this.createRowsData(); } /** * 通过tableData生成 columnsData * @returns */ createColumnsData = () => { let columnsData = []; if (this.data.length > 0) columnsData = Object.keys(this.data[0]); return columnsData; } /** * 通过tableData生成 rowsData * @returns */ createRowsData = () => { let rowData = []; this.data.map(item => { rowData.push(Object.values(item)); }); return rowData; } /** * 函数设置width属性值 * @param {*} columnIndex */ static calculateWidth = (columnIndex, columnWidth) => { let tempArr = []; if (typeof columnWidth === "number") { return columnWidth; } else if (typeof columnWidth === "object") { columnWidth.map((k, index) => { if (typeof k.columnsIndex === "object") { k.columnsIndex.map(innerK => { tempArr.push({ columnsIndex: innerK, width: k.width }); }); } else { tempArr.push(columnWidth[index]); } }); } let width = 0; tempArr.map((k) => { switch (columnIndex) { case k.columnsIndex: width = k.width; break; } }); return width; } /** * 将英文列名改为中文列名(id不显示) * @param {*} columnIndex */ static transferColumnName = (columnIndex, cnColumnNameArr) => { return cnColumnNameArr[columnIndex]; } /** * 隐藏列 * @param {*} columnIndex */ static handleHiddenColumns = (columnIndex, hiddenIndex) => { return hiddenIndex.includes(columnIndex); } /** * 生成列名: cnColumnNameArr有值则使用中文名,无值使用原this.column值 * @param {*} columnsArr */ generateColumns(cnColumnNameArr, hiddenIndex, columnWidth) { console.log(cnColumnNameArr, this.column); if (cnColumnNameArr) this.column = cnColumnNameArr; return this.column.map((item, columnIndex) => { return { key: `${item}`, dataKey: `${item}`, title: `${item}`, // 通过函数设置width值 hidden: hiddenIndex.length > 0 ? GenerateTableData.handleHiddenColumns(columnIndex, hiddenIndex) : false, width: GenerateTableData.calculateWidth(columnIndex, columnWidth), align: 'center', }; }) } // 生成列表数据 generateData = (columns) => { return this.rowData.map((item, rowIndex) => { return columns.reduce( (rowData, column, columnIndex) => { // item数组下标columnIndex-1开始(id不显示),因为有checkbox复选框 rowData[column.dataKey] = item[columnIndex]; return item; }, // 初始化元素为第一条数据(否则数据会获取不到id)tempDataArr[0] this.rowData[rowIndex] ) }) } /** * 增加全选列且操作全选/全不选 ; 增加操作按钮:修改,删除 * @param {*} columns */ static customizeColumns = (columns, data, selectedId, cellRendererFunc) => { // 全选按钮:在数组头部添加 columns.unshift({ key: 'selection', dataKey: 'selection', title: 'selection', width: 30, cellRenderer: ({ rowData }) => { // 绑定数据的id,然后row-key才能使用id rowData.id = rowData[0]; const onChange = (value) => { rowData.checked = value if (rowData.checked) { selectedId.push(rowData[0]); } else { let idIndex = selectedId.findIndex(item => item === rowData[0]); selectedId.splice(idIndex, 1); } console.log("selectedId.value------------", selectedId); return rowData.checked; } return ( < ElCheckbox onChange = { onChange } modelValue = { rowData.checked } indeterminate = { false } /> ) }, headerCellRenderer: () => { const _data = unref(data) const onChange = (value) => (data = _data.map((row) => { row.checked = value; // 全选id设置 if (row.checked) { selectedId.push(row[0]); } else { selectedId = []; } return row; })) // 全选 const allSelected = _data.every((row) => row.checked) // 非全选 const containsChecked = _data.some((row) => row.checked) return ( < ElCheckbox onChange = { onChange } modelValue = { allSelected } indeterminate = { containsChecked && !allSelected } /> ) }, }); // 操作按钮:在数组末尾添加 cellRendererFunc && columns.push({ key: 'operations', dataKey: 'operations', title: '操作', width: 300, align: 'center', // 编辑和删除操作:绑定当前id,使用的是JSX语法,方法调用onClick={ editResource } 传参:onClick={ (event)=>editResource(rowData[0]) } cellRenderer: ({ rowData }) => cellRendererFunc(rowData) }); }; /** * 固定列:可以用这个方法也可以用elementplus自带的(自带的感觉还方便一些) */ fixedColumns = (columns, fixedColumnIndex) => { fixedColumnIndex.length > 0 && fixedColumnIndex.map(column => { // 不设置为TableV2FixedDir.LEFT这种形式,可以直接写true,默认left let tableV2Fixed = true; if (column.direction === "left") tableV2Fixed = TableV2FixedDir.LEFT; if (column.direction === "right") tableV2Fixed = TableV2FixedDir.RIGHT; columns[column.index].fixed = tableV2Fixed; }); } }
4.父类中调用类方法
// 数据所有列都一样,所以取第一条数据列名作为表头 let cnColumnNameArr = ['编号', '资源名称', '资源类型', '提交原因', '上个投产版本', '投产版本', '提交人', 'SIT' , '提交时间', '状态', 'SIT部署时间', 'SIT测试完成时间', 'UAT部署时间', 'SIT部署完成', 'SIT已测试', 'UAT部署完成']; let hiddenIndex = [0,4]; let columnWidth = [{columnsIndex:[0,4],width:0}, {columnsIndex:1,width:146}, {columnsIndex:2,width:80}, {columnsIndex:3,width:300}, {columnsIndex:5,width:76}, {columnsIndex:[6,9],width:100}, {columnsIndex:[8,10,11,12],width:160}, {columnsIndex:[7,13,14,15],width:70}, {columnsIndex:'default',width:58}]; const generateTableData = new GenerateTableData(tableData.value); // 完全无值也需要显示列名, cnColumnNameArr此处必须有值:cnColumnNameArr或者false(英文列名) cnColumnNameArr = tableData.value.length === 0? cnColumnNameArr : cnColumnNameArr;//length如果不为0是设置为false就会显示英文列名 columns.value = generateTableData.generateColumns(cnColumnNameArr,hiddenIndex,columnWidth); // 设置全选按钮和操作按钮 data.value = code === 200 ? generateTableData.generateData(columns.value): []; GenerateTableData.customizeColumns(columns.value,data.value,selectedId.value,cellRenderer); if(code === 200){ // 固定列 columns.value[0].fixed = true columns.value[1].fixed = TableV2FixedDir.LEFT columns.value[2].fixed = TableV2FixedDir.LEFT columns.value[3].fixed = TableV2FixedDir.LEFT } resizeColumns(columns.value);
5.父子组件通信(provide/inject)
父组件:
// provide方式父子组件传值 provide('columns', computed(()=>columns.value)); provide('data', computed(()=>data.value)); // 分页 provide('showPage', computed(()=>true)); provide('pageNum', computed(()=>pageNum.value)); provide('total', computed(()=>total.value)); provide('pageSize', computed(()=>pageSize.value)); provide('pages', computed(()=>pages.value)); // 是否宽高自适应 provide('selfAdaption', computed(()=>true)); provide('cellRenderer', computed(()=>cellRenderer));
子组件:
// 是否显示分页组件 const showPage = inject('showPage',false); const columns = inject('columns',[]); const data = inject('data',[]); const pageNum = inject('pageNum',1); const pages = inject('pages',0); const total = inject('total',0); const pageSize = inject('pageSize',16); // 是否宽高自适应 const selfAdaption = inject('selfAdaption',false);
6.分页
子组件:
const $emit = defineEmits(['handlePagenation']); /** * 上一页:pageNum会自动-1 */ const prevClick = () => { // pageNation分页组件限定,pageNum.value不可能为0;如果pageNum.value比1大就取pageNum.value,否则永远为1 $emit('handlePagenation', Math.max(1, pageNum.value)); } /** * 下一页:pageNum会自动+1 */ const nextClick = () => { // 如果pageNum.value比pages小就取pageNum.value,否则永远为pages $emit('handlePagenation', Math.max(1, Math.min(pages.value, pageNum.value))); } /** * 点击特定页码(此方法会自动传入当前页码) * @param {*} currentPage */ const currentChange = (currentPage) => { $emit('handlePagenation', currentPage); }
父组件:
/** * 分页 */ const handlePagenation = (pageNumVal) =>{ // pageNation分页组件限定,pageNum.value不可能为0;如果pageNum.value比1大就取pageNum.value,否则永远为1 pageNum.value = pageNumVal; loadDataGrid(); }
7.问题:el-table-v2中数据失去响应性
以上,实现简单封装
总结
到此这篇关于vue3+elementplus基于el-table-v2封装公用table组件的文章就介绍到这了,更多相关el-table-v2封装公用table组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- vue3 实现关于 el-table 表格组件的封装及调用方法
- vue3+ts+vite使用el-table表格渲染记录重复情况
- Vue3中el-table表格数据不显示的原因和解决方法
- 解决vue3中from表单嵌套el-table时填充el-input,v-model不唯一问题
- vue3插槽:el-table表头插入tooltip及更换表格背景色方式
- vue3使用element-plus中el-table组件报错关键字'emitsOptions'与'insertBefore'分析
- vue3 el-table结合seamless-scroll实现表格数据滚动的思路详解
- vue3 el-table 如何通过深度选择器::v-deep修改组件内部样式(默认样式)