前端封装el-table及注意点
发布时间:2026/8/28 7:46:32 作者:尧图编辑部 阅读量:1,286

table封装文件templatedivclasstableBoxel-table:dataprops.tDatastylewidth:100%height100%:borderprops.borderstripehighlight-current-rowreftableRefselection-changehandleSelectionChange!-- 多选列 --el-table-columntypeselectionwidth55v-ifprops.showSelection/!-- 序号 --el-table-columnlabel序号width60aligncenterv-ifprops.showIndextemplate#default{$index}{{ (props.pageNum -1) * props.pageSize $index 1 }}/template/el-table-columnel-table-columnv-for(item, index) in props.configColumns:keyindex:propitem.prop:labelitem.label:widthitem.widthshow-overflow-tooltipaligncenter!-- 自定义列 --template#default{row}slot:namecol-${item.prop}:rowrow{{ row[item.prop] }}/slot/template/el-table-column!-- 操作列 --el-table-columnlabel操作v-if$slots[action]:widthprops.actionWidth || 180aligncentertemplate#default{row}slotnameaction:rowrow/slot/template/el-table-column/el-table/div/templatescriptsetupimport{ref,onMounted,reactive,}fromvueimport{ElMessage,ElMessageBox}fromelement-plus;consttableRefref()constemitdefineEmits([selection-change])constpropsdefineProps({tData:{type:Array,default:()[]},configColumns:{type:Array,default:()[]},border:{type:Boolean,default:false,},actionWidth:{type:Number,default:180,},showIndex:{type:Boolean,default:false,},showSelection:{type:Boolean,default:false,},pageNum:{type:Number,default:1,},pageSize:{type:Number,default:10,},})consthandleSelectionChange(selectedRows){emit(selection-change,selectedRows)}consttableClearSelection(){tableRef.value.clearSelection()}defineExpose({tableClearSelection})conststatereactive({})onMounted((){})/scriptstylelangscssscoped.tableBox{margin-bottom:1%;}/style组件中使用el-buttontypeinfoplainclickresetHandle重置/el-buttonel-buttontypeprimaryclick.stopdeleteBatchHandle批量删除/el-buttondivclasstableBoxfe-table:tDatatableData:configColumnscsOptionsborder:showIndextrue:showSelectiontrue:pageNumpage.pageNum:pageSizepage.pageSizeselection-changeonSelectionChangereffeTableRef!-- 自定义列 --template#col-cslb{row}el-tag:typerow.cslb 0 ? success : danger{{ row.cslb 0 ? 启用 : 停用 }}/el-tag/template!-- 自定义列添加颜色 --template#col-csmc{ row }spanstylecolor:#1890ff;font-weight:bold;{{ row.csmc }}/span/template!-- 操作列 --template#action{row}:widthprops.actionWidth || 180el-buttontypeprimarylinkclickdeleteHandle(row)删除/el-buttonel-buttontypeprimarylinkclickseeHandle(row)查看/el-button/template/fe-table/divdivclasspageBoxel-paginationbackgroundsize-changesizeChangecurrent-changecurrentChange:current-pagepage.pageNum:page-sizepage.pageSize:page-sizes[10, 20, 50, 100,]layouttotal,sizes,prev,pager,next,jumper:totaltotal/el-pagination/divscriptsetupimport{ref,onMounted,reactive,}fromvueimportFeTablefrom/components/fe-table/fe-table.vueconstfeTableRefref()consttableDataref([{id:0,csmc:名称,cslb:0,csbh:编号,ssfj:单位,},{id:1,csmc:名称,cslb:1,csbh:编号,ssfj:单位,},{id:2,csmc:名称,cslb:0,csbh:编号,ssfj:单位,},{id:3,csmc:名称,cslb:1,csbh:编号,ssfj:单位,},{id:4,csmc:名称,cslb:1,csbh:编号,ssfj:单位,},{id:5,csmc:名称,cslb:1,csbh:编号,ssfj:单位,},{id:6,csmc:名称,cslb:0,csbh:编号,ssfj:单位,},])constcsOptionsref([{prop:csmc,label:场所名称},{prop:cslb,label:场所类别},{prop:csbh,label:场所编号},{prop:ssfj,label:所属单位},])consttotalref(0)constpagereactive({pageSize:10,pageNum:1,})conststatereactive({selectList:[]})constsizeChange(val){page.pageSizeval}constcurrentChange(val){page.pageNumval}constonSelectionChange(selectList){console.log(selectList,选中行)state.selectListselectList}// 清空表格多选比如切换分页、查询重置时调用constresetHandle(){feTableRef.value.tableClearSelection()// 清空表格多选}//批量删除constdeleteBatchHandle(){if(state.selectList.length0){ElMessage.warning(请选择至少一条数据)return}constselectIdsstate.selectList.map(elel.id)ElMessageBox.confirm(此操作将删除该数据,是否继续?,提示,{confirmButtonText:确定,cancelButtonText:取消,type:warning}).then((){console.log(可以发请求了)// xxxxAPI({ idList: ids }).then(res{// console.log(res.data, ddd)// if(res.data.code 200){// ElMessage.success(res.data.msg)// getList()// }else{// ElMessage.error(res.data.msg)// }// })})}/script涉及的知识点连续序号(pageNum‑1)*pageSize $index 1切换分页时序号不会从 1 重新开始分页组件里修改 pageNum、pageSize 传给 fe‑table 即可。不同页面不同单元格渲染动态命名插槽插槽命名规则#col-字段名哪个页面需要特殊渲染就写对应插槽不需要就不写自动展示原始值。操作列每个页面独立封装组件只预留插槽按钮、事件全部在业务页面写多个业务页面引入 fe‑table各自写自己的#action互不干扰。一、详解 动态命名插槽!-- fe-table 组件封装里的写法 --!-- 自定义列 --template#default{row}slot:namecol-${item.prop}:rowrow{{ row[item.prop] }}/slot/template!-- 业务组件中使用时的写法 --!-- 只针对 effectFlag 字段进行单元格渲染 --template#col-effectFlag{ row }span{{ row.effectFlag 0 ? 启用 : 停用 }}/span/templatecol-${item.prop}是动态插槽名col是前缀根据需求可以自主命名item.prop就是列配置里的字段名例如 effectFlag、name、createTime当 item.prop “name” → 实际插槽名字col-name当 item.prop “effectFlag” → 实际插槽名字col-effectFlag{ row }是插槽传出来的行对象可以拿到当前行全部数据。name、createTime 没有写对应插槽就会走组件内部默认 {{ row.name }}原样输出。坑点 插槽名严格匹配col‑effectFlag不能写错大小写prop 是什么插槽后缀就是什么。二、外部传入操作列插槽 action场景表格的操作列每个页面按钮完全不一样页面 A编辑、删除页面 B查看、复制、导出页面 C审核、驳回使用方法fe-table组件里写!-- 如果外部使用了 table‑operate 插槽才渲染这一列 --el-table-columnlabel操作:widthprops.actionWidth || 180v-if$slots[action]aligncentertemplate#default{ row }!-- 把 row 行数据透传给外部插槽外部拿row做按钮事件 --slotnameaction:rowrow/slot/template/el-table-columnaction是自己起的名字你也可以叫 table-operate 或者其他$slots[action]是Vue内置判断父组件有没有传入这个名字的插槽。没有就不渲染操作列。如果某个页面不需要操作列直接不写 #action 模板组件内部v‑if$slots[action]自动隐藏操作列业务页面使用!-- A页面使用 --fe-table:tDatatableData:configColumnscsOptions......!-- 操作列当前页面自己写按钮和事件 --template#action{ row }el-buttonlinktypeprimaryclickhandleEdit(row)编辑/el-buttonel-buttonlinktypedangerclickhandleDel(row)删除/el-button/template/fe-table!-- B页面使用 --fe-table:tDatatableData2:configColumnscsOptions2......template#action{ row }el-buttonlink查看/el-buttonel-buttonlink复制/el-buttonel-buttonlink审核/el-button/template/fe-table最后两者对比总结类型动态字段插槽 column‑xxx操作列插槽 action用途普通单元格自定义渲染状态转换、标签、格式化整列操作按钮编辑 / 删除 / 审核插槽命名根据 prop 动态生成#column‑prop值固定名字 #action触发条件需要特殊格式化的列才写不写用默认值需要操作按钮才写不写整列消失传参{ row } 当前行数据{ row } 当前行数据组件改动组件只写兜底显示业务接管覆盖组件只渲染外壳列按钮全部交给业务常见踩坑prop 大小写要和插槽后缀完全一致prop:effectFlag →插槽 #column-effectFlag不能写成 #column‑EffectFlag。动态插槽语法v-slot:[column-${item.prop}]里面是反引号不是单引号。插槽解构 {row} 不要丢否则拿不到行数据。操作列不写插槽模板就不会出现操作列不需要手动加 v‑if 控制。