记录一下在对el-tabel进行简单封装并实现行内编辑,单元格合并等功能
id="iTable" v-loading.iTable="options.loading"//是否添加表格loading加载动画 :data="list"//数据列 :stripe="options.stripe"// 是否添加表格loading加载动画 ref="multipleTable"// 是否支持列表项选中功能 border :default-sort="{order: 'descending'}" @selection-change="handleSelectionChange" @filter-change="filterchange" :header-cell-style="rowClass"//多级表头控制样式 :header-cell-class-name="headerStyle"//表头样式 :row-class-name="tableRowClassName"//行样式 :span-method="objectSpanMethod"//合并单元格 :height="height"//高度 size="small" :row-style="{height:'30px'}" :cell-style="{padding:'0px'}" @row-click="rowclick"//行点击事件 @row-dblclick="dblclick"//双击 @row-contextmenu="contmenuclick"//右键 @cell-click="cellclick"//单元格事件 > //是否为多级,如果为多级,另一个组件循环(代码放下面) :prop="column.prop" :key="column.label" :label="column.label" :align="column.align" :min-width="column.width" :fixed="column.fixed" :filters="column.filters" sortable > v-for="item in column.SelectObj" :key="item.value" :label="item.label" :value="item.value"> v-model="scope.row[column.prop]" type="datetime" placeholder="Select date and time" default-time="12:00:00"> v-for="item in column.SelectObj" :key="item.value" :label="item.label" :value="item.value"> v-model="scope.row[column.prop]" type="date" placeholder="Pick a day" > {{scope.row[column.prop]}} :column="column" :row="scope.row" :render="column.render" :index="index" > ref="fixedColumn" label="操作" align="center" :width="operates.width" :fixed="operates.fixed" v-if="operates.list.filter(_x=>_x.show=== true).length > 0" > v-if="!scope.row.isEdit" type="primary" size="mini" icon="el-icon-edit" plain round @click.stop="EditButtonEvent(scope.$index, scope.row)">编辑 v-if="!scope.row.isEdit" size="mini" type="danger" icon="el-icon-delete" plain round @click.stop="DeleteButtonEvent(scope.$index, scope.row)">删除 v-if="scope.row.isEdit" size="mini" type="info" icon="el-icon-refresh-right" plain round @click.stop="CancelButtonEvent(scope.$index, scope.row)">取消 v-if="scope.row.isEdit" size="mini" type="success" icon="el-icon-refresh" plain round @click.stop="SaveButtonEvent(scope.$index, scope.row)">保存 @size-change="handleSizeChange" @current-change="handleIndexChange" :page-size="pageSize" :page-sizes="[5,10,20,30,50,100]" :current-page="pageIndex" layout="total,sizes, prev, pager, next,jumper" :total="total" > import MyColumnfrom "./MyColumn"; export default { props: { // 数据列表 list: { type: Array, default: [] }, //表格高度 height: { type: Number, default:400 }, // 需要展示的列 === prop:列数据对应的属性,label:列名,align:对齐方式,width:列宽 columns: { type: [Array, Object], default: [] }, // 总数 total: { type: Number, default:0 }, // 每页显示的数量 pageSize: { type: Number, default:10 }, // 操作按钮组 === label: 文本,type :类型(primary / success / warning / danger / info / text), // show:是否显示,icon:按钮图标,plain:是否朴素按钮,disabled:是否禁用,method:回调方法 operates: {}, // table 表格的控制参数 options: { type: Object, default: { // 是否为斑马纹 table stripe:false, // 是否要高亮当前行 highlightCurrentRow:false } }, //需要合并的数据源 mergeData:{ type: [Array,Object], default: ()=>({ data:[],//要合并的数据源 columnIndex:[],//要合并的列的索引 columnName:[],//要合并的列的名称 }), }, //需要表示状态行的标识 rowSign:{ type:[Array,Object], default:()=>({ index:[],//比较字段在对象中的索引 type:'',//判断是什么操作(状态值、正负值、区间值比) data:[],//需要比较的值、以及返回表格类样式 }) }, //是否需要分页部分 pageShow:{ type:Boolean, default:true } }, //组件 components: { MyColumn, expandDom: { functional:true, props: { row: Object, render: Function, index: Number, column: { type: Object, default:null }, }, render:(h, ctx) =>{ const params = { row: ctx.props.row, index: ctx.props.index, size: ctx.props.size, round: ctx.props.round, circle: ctx.props.circle, plain: ctx.props.plain, show: ctx.props.show }; if (ctx.props.column) params.column = ctx.props.column; //实现下拉框 if(ctx.props.row.isEdit&&ctx.props.column.isSelect) { return h('el-select',{ props:{ value:ctx.props.row.state }, on: { 'change':(event) => { ctx.props.row.state=event; } }, },[ctx.props.column.SelectObj.map((val) => {// 下拉框里的内容,optionList下拉框数据 return h('el-option', { props: { value: val.value, label: val.label } }) }) ]); } //实现输入框 if(ctx.props.column.isEdit&&!ctx.props.column.isSelect) { debugger; return h('input',{ style:{ height:'28px !important', 'border-radius':'4px !important', border:'1px solid #DCDFE6', }, domProps: { value:params.row.state }, props:{ value:params.row.state }, on: { click(event){ event.stopPropagation(); }, input(event) { params.row.state=event.target.value; } } }) } return ctx.props.render(h, params); } } }, // 数据 data() { return { position:0, rowSpanArr: [], pageIndex:1, multipleSelection:[], rowInfo: [],//选中行数据 }; }, created(){ this.getRowSpan(); }, mounted() {}, computed: {}, methods: { //切换每页显示的条数 handleSizeChange(size) { this.pageIndex =1; this.$emit("handleSizeChange", size); }, // 切换页码 handleIndexChange(index) { this.$emit("handleIndexChange", index); this.pageIndex = index; }, // 多行选中 handleSelectionChange(val) { this.multipleSelection = val; this.$emit("handleSelectionChange", val); }, //table行样式设置 tableRowClassName({ row, rowIndex }) { switch (this.rowSign.type) { case 'state': for(let i=0;i { if(Object.values(row)[this.rowSign.index]===this.rowSign.data[i].Id) return this.rowSign.data[i].className; } break; case 'bool': if(Object.values(row)[this.rowSign.index[0]]>0) return 'success-row'; else if(Object.values(row)[this.rowSign.index[0]]<0) return 'warning-row'; break; case 'section': let num=Object.values(row)[this.rowSign.index[0]]; for(let i=0;i { if(num>=this.rowSign.data[i].Number1&&num<=this.rowSign.data[i].Number2) return this.rowSign.data[i].className; } break; default: break; } return ""; }, //合并单元格 objectSpanMethod({ row, column, rowIndex, columnIndex }) { if(this.mergeData.columnIndex.length>0) { for(let i=0;i { if (columnIndex ===this.mergeData.columnIndex[i]) { const _row =this.rowSpanArr['rowSpanArr'+i][rowIndex]; const _col = _row >0 ?1 :0; return { rowspan: _row, colspan: _col } } } } }, // 获取合并的数组 getRowSpan() { let that=this; this.rowSpanArr = {}; let data_=that.mergeData.data; for(let i=0;i { let name=that.mergeData.columnName[i]; that.mergeData.data.forEach((item, index) => { if (index===0) { that.rowSpanArr['rowSpanArr'+i] =[]; that.rowSpanArr['rowSpanArr'+i].push(1); that.position =0; }else { if (data_[index][name]===data_[index -1][name]) { that.rowSpanArr['rowSpanArr'+i][that.position] +=1; //项目名称相同,合并到同一个数组中 that.rowSpanArr['rowSpanArr'+i].push(0); data_[index][name] = data_[index -1][name]; }else { that.rowSpanArr['rowSpanArr'+i].push(1); that.position = index; } } }); } }, //筛选方法 filterchange(value) { this.$emit("filterchange", value); return value; }, //table单击事件 rowclick(row, col, event) { this.$emit("rowclick", row, col, event); }, //双击事件 dblclick(val) { this.$emit("dblclick", val); }, //右键事件 contmenuclick(val) { this.$emit("contmenuclick", val); }, //单元格点击事件 cellclick(row, col, cell, event) { this.$emit("cellclick", row, col, cell, event); }, rowClass({ row, rowIndex}){ return "background:rgba(236,240,245,0.4)"; }, headerStyle ({row, column, rowIndex, columnIndex}) { if(row&&row[0].children) { return 'speHeader'; } }, //编辑按钮事件 EditButtonEvent(index,row) { this.$emit("EditButtonEvent", index, row); }, //删除按钮事件 DeleteButtonEvent(index,row) { this.$emit("DeleteButtonEvent", index, row); }, //取消按钮事件 CancelButtonEvent(index,row) { this.$emit("CancelButtonEvent", index, row); }, //保存按钮事件 SaveButtonEvent(index,row) { this.$emit("SaveButtonEvent", index, row); } }, watch:{ mergeData:{ handler(newVal,oldVal){ this.getRowSpan(); }, deep:true, immediate:true }, } }; .el-table .warning-row { background:#fd9165; } .el-table .success-row { background:#94f987; } .el-table .danger-row { background:#f9400b; } .el-table .primary-row { background:#abb7f9; } .speHeader{ color:blue } .el-input__inner{ height:28px !important;; } :prop="col.prop" :label="col.label" :min-width="col.width" :fixed="col.fixed" align="center" :filters="col.filters" > v-for="item incol.SelectObj" :key="item.value" :label="item.label" :value="item.value"> v-for="item incol.SelectObj" :key="item.value" :label="item.label" :value="item.value"> {{scope.row[col.prop]}} :column="col" :row="scope.row" :render="col.render" :index="index"> v-for="(item, index) incol.children" :key="index" :col="item" > export default { name:"MyColumn", props: { col: { type: Object } }, methods:{ myclass(){ return 'MyHeader' }, } } .el-table thead tr:nth-child(1) { color:blue !important; }