vue3+elementplus基于el-table-v2封裝公用table組件詳細代碼
1.梳理出需要封裝的功能
主要是針對表格進行封裝,不包括查詢表單和操作按鈕。
梳理出系統(tǒng)中通用表格的功能項,即表格主體的所有功能,生成columns列頭數(shù)據(jù)、生成data表體數(shù)據(jù)、拖拉列寬、分頁、生成中文列名、自定義列寬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.將生成列名和表體數(shù)據(jù)、復(fù)選框、操作按鈕等方法封裝成類
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; } /** * 函數(shù)設(shè)置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}`, // 通過函數(shù)設(shè)置width值 hidden: hiddenIndex.length > 0 ? GenerateTableData.handleHiddenColumns(columnIndex, hiddenIndex) : false, width: GenerateTableData.calculateWidth(columnIndex, columnWidth), align: 'center', }; }) } // 生成列表數(shù)據(jù) generateData = (columns) => { return this.rowData.map((item, rowIndex) => { return columns.reduce( (rowData, column, columnIndex) => { // item數(shù)組下標columnIndex-1開始(id不顯示),因為有checkbox復(fù)選框 rowData[column.dataKey] = item[columnIndex]; return item; }, // 初始化元素為第一條數(shù)據(jù)(否則數(shù)據(jù)會獲取不到id)tempDataArr[0] this.rowData[rowIndex] ) }) } /** * 增加全選列且操作全選/全不選 ; 增加操作按鈕:修改,刪除 * @param {*} columns */ static customizeColumns = (columns, data, selectedId, cellRendererFunc) => { // 全選按鈕:在數(shù)組頭部添加 columns.unshift({ key: 'selection', dataKey: 'selection', title: 'selection', width: 30, cellRenderer: ({ rowData }) => { // 綁定數(shù)據(jù)的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設(shè)置 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 } /> ) }, }); // 操作按鈕:在數(shù)組末尾添加 cellRendererFunc && columns.push({ key: 'operations', dataKey: 'operations', title: '操作', width: 300, align: 'center', // 編輯和刪除操作:綁定當(dāng)前id,使用的是JSX語法,方法調(diào)用onClick={ editResource } 傳參:onClick={ (event)=>editResource(rowData[0]) } cellRenderer: ({ rowData }) => cellRendererFunc(rowData) }); }; /** * 固定列:可以用這個方法也可以用elementplus自帶的(自帶的感覺還方便一些) */ fixedColumns = (columns, fixedColumnIndex) => { fixedColumnIndex.length > 0 && fixedColumnIndex.map(column => { // 不設(shè)置為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.父類中調(diào)用類方法
// 數(shù)據(jù)所有列都一樣,所以取第一條數(shù)據(jù)列名作為表頭 let cnColumnNameArr = ['編號', '資源名稱', '資源類型', '提交原因', '上個投產(chǎn)版本', '投產(chǎn)版本', '提交人', 'SIT' , '提交時間', '狀態(tài)', '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是設(shè)置為false就會顯示英文列名 columns.value = generateTableData.generateColumns(cnColumnNameArr,hiddenIndex,columnWidth); // 設(shè)置全選按鈕和操作按鈕 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)); // 是否寬高自適應(yīng) 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); // 是否寬高自適應(yīng) 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))); } /** * 點擊特定頁碼(此方法會自動傳入當(dāng)前頁碼) * @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中數(shù)據(jù)失去響應(yīng)性
以上,實現(xiàn)簡單封裝
總結(jié)
到此這篇關(guān)于vue3+elementplus基于el-table-v2封裝公用table組件的文章就介紹到這了,更多相關(guān)el-table-v2封裝公用table組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Vue-cli3.0創(chuàng)建的項目 如何發(fā)布npm包
這篇文章主要介紹了使用Vue-cli3.0創(chuàng)建的項目,如何發(fā)布npm包,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10Vue.js通用應(yīng)用框架-Nuxt.js的上手教程
本篇文章主要介紹了Vue.js通用應(yīng)用框架-Nuxt.js的上手教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12iView UI FORM 動態(tài)添加表單項校驗規(guī)則寫法實例
這篇文章主要為大家介紹了iView UI FORM 動態(tài)添加表單項校驗規(guī)則寫法實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01