1.初始化一个element的table表格,选中一个单元格选择合并行和列,参考element文档需要使用到的方法是objectSpanMethod,注意:objectSpanMethod参数行和列都是从0开始,比如第一行第一列单元格位置是(0,0),要合并的行和列最小为1
2.实现效果如下:
3.代码如下:
<template>
<div class="content">
<div class="table_box" v-if="show">
<el-table
ref="singleTable"
:data="tableData"
highlight-current-row
@current-change="handleCurrentChange"
border
:span-method="objectSpanMethod"
@cell-dblclick = "dbclick"
:cell-class-name="tableCellClassName"
@cell-click="cellClick"
>
<el-table-column
v-for="(item,key,index) in tableColumns"
:key="index"
:label="item.label"
:prop="item.children?'':item.prop"
width="180">
<el-popover
placement="right"
width="400"
slot-scope="scope"
trigger="click">
<el-button size="mini" type="primary" @click="dialogVisible = true">合并单元格</el-button>
<el-button size="mini" type="primary" @click="addTr('top',selectTab.tr)">向上插入一行</el-button>
<el-button size="mini" type="primary" @click="addTr('bottom',selectTab.tr)">向下插入一行</el-button>
<div slot="reference">
<span>{{ scope.row[item.prop] }}</span>
</div>
</el-popover>
<div v-if="item.children && item.children.length>0">
<el-table-column
v-for="(val,i) in item.children"
:key="i"
:prop="val.prop"
:label="val.label"
width="180">
<!-- <template slot-scope="scope">
<span>{{ scope.row[val.prop] }}22</span>
</template> -->
<el-popover
placement="right"
width="400"
slot-scope="scope"
trigger="click">
<el-button size="mini" type="primary" @click="dialogVisible = true">合并单元格</el-button>
<el-button size="mini" type="primary" @click="addTr('top',selectTab.tr)">向上插入一行</el-button>
<el-button size="mini" type="primary" @click="addTr('bottom',selectTab.tr)">向下插入一行</el-button>
<div slot="reference">
<span>{{ scope.row[val.prop] }}</span>
</div>
</el-popover>
</el-table-column>
</div>
</el-table-column>
</el-table>
</div>
<el-dialog
title="合并"
:visible.sync="dialogVisible"
width="300px"
>
<el-form ref="form" label-width="80px">
<el-form-item label="合并行">
<el-input :min="0" v-model="selectTab.trSpan"/>
</el-form-item>
<el-form-item label="合并列">
<el-input :min="0" v-model="selectTab.tdSpan"/>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small">取 消</el-button>
<el-button type="primary" @click="addMerge" size="small">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data(){
return{
tableData:[],//表格数据
tableColumns:[],//表头数据
show:false,
currentRow: null,
spanArr:[],
selectTab:{
tr:0,//第几行
td:0,//第几列
trSpan:1,//占几行
tdSpan:1,//占几列
},
mergeList:[],//记录合并详情
dialogVisible:false,
}
},
watch:{
// mergeList:{//监听合并列表项
// handler(newVal,oldVal){
// console.log('刷新');
// this.show = false;
// this.$nextTick(()=>{
// this.show = true;
// })
// },
// deep:true
// }
},
mounted(){
this.init();
},
methods:{
tableCellClassName({row, column, rowIndex, columnIndex}){
//注意这里是解构
//利用单元格的 className 的回调方法,给行列索引赋值
row.index=rowIndex;
column.index=columnIndex;
},
cellClick(row, column, cell, event){
console.log('rowIndex',row.index);
console.log('colIndex',column.index);
this.selectTab.tr = row.index+1;
this.selectTab.td = column.index+1;
},
dbclick(row, column, cell, event){
console.log('row:',row);
console.log('column:',column,);
console.log('cell:',cell);
console.log('event:',event);
this.selectTab.tr = row.index+1;
this.selectTab.td = column.index+1;
},
addMerge(){//合并项添加进合并列表中
// let obj = this.mergeList.filter(item=>item.td==this.selectTab.td&&item.tr)
let flag = false;
let w = -1;
this.mergeList.forEach((item,index)=>{
if(item.td==this.selectTab.td && item.tr==this.selectTab.tr){//是否有重复项,有则替换
flag = true;
w = index;
}
})
if(flag){
this.mergeList[w] = Object.assign({},this.selectTab);
}else{
this.mergeList.push(Object.assign({},this.selectTab));
}
this.dialogVisible = false;
this.show = false;//手动刷新
this.$nextTick(()=>{
this.show = true;
})
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {//表格的合并函数
//console.log('列',columnIndex,rowIndex);
//console.log('行',row,column);0,2
// let td = Number(this.selectTab.td)-1;//columnIndex从0开始
// let tr = Number(this.selectTab.tr)-1;//rowIndex从0开始
// if( columnIndex>=td && columnIndex<=((Number(td)+Number(this.selectTab.trSpan))-1)){
// if( rowIndex>=tr && rowIndex<=((Number(tr)+Number(this.selectTab.tdSpan))-1)){
// if(columnIndex==td && rowIndex==tr){
// return [this.selectTab.tdSpan,this.selectTab.trSpan]
// }else{
// console.log('选择的行列',columnIndex,rowIndex);
// console.log('选择的列',this.selectTab.td,(Number(this.selectTab.td)+Number(this.selectTab.tdSpan))-1);
// console.log('选择的行',this.selectTab.tr,(Number(this.selectTab.tr)+Number(this.selectTab.trSpan))-1);
// return [0,0]
// }
// }
// }
if(this.mergeList.length>0){
console.log('merge',this.mergeList);
for(let i=0;i<this.mergeList.length;i++){
let item = this.mergeList[i];
let td = Number(item.td)-1;//columnIndex从0开始
let tr = Number(item.tr)-1;//rowIndex从0开始
if( columnIndex>=td && columnIndex<=((Number(td)+Number(item.trSpan))-1)){
if( rowIndex>=tr && rowIndex<=((Number(tr)+Number(item.tdSpan))-1)){
if(columnIndex==td && rowIndex==tr){
console.log('选中的行列',columnIndex,rowIndex,item.tdSpan,item.trSpan);
return [item.tdSpan,item.trSpan]
}else{
console.log('选择的行列',columnIndex,rowIndex);
// console.log('选择的列',this.selectTab.td,(Number(this.selectTab.td)+Number(this.selectTab.tdSpan))-1);
// console.log('选择的行',this.selectTab.tr,(Number(this.selectTab.tr)+Number(this.selectTab.trSpan))-1);
return [0,0]
}
}
}
}
}
//forEach中使用return不会中断,相当于continue
// this.mergeList.forEach(item=>{
// let td = Number(item.td)-1;//columnIndex从0开始
// let tr = Number(item.tr)-1;//rowIndex从0开始
// if( columnIndex>=td && columnIndex<=((Number(td)+Number(item.trSpan))-1)){
// if( rowIndex>=tr && rowIndex<=((Number(tr)+Number(item.tdSpan))-1)){
// if(columnIndex==td && rowIndex==tr){
// console.log('选中的行列',columnIndex,rowIndex,item.tdSpan,item.trSpan);
// return [item.tdSpan,item.trSpan]
// }else{
// console.log('选择的行列',columnIndex,rowIndex);
// // console.log('选择的列',this.selectTab.td,(Number(this.selectTab.td)+Number(this.selectTab.tdSpan))-1);
// // console.log('选择的行',this.selectTab.tr,(Number(this.selectTab.tr)+Number(this.selectTab.trSpan))-1);
// return [0,0]
// }
// }
// }
// })
},
init(){//初始化表格
// if(this.tdCount==0){
// this.tableColumns = [{label:'默认',prop:'default'}];
// this.tableData = [{default:0}];
// }
this.tableColumns = [
{label:'默认',prop:'default'},
{label:'双十一',prop:'',children:[{label:'库存',prop:'count'},{label:'销量',prop:'sale'}]},
];
this.tableData = [
{default:0,count:111,sale:100},
{default:0,count:173,sale:220},
{default:0,count:89,sale:120}
];
this.show = true;
},
addTab(){//插入表头
if(this.tableColumns.every(item=>item.label!=this.tab.label)){
this.tableColumns.push(Object.assign({},this.tab));
}else{
this.$notify.error({
title: '错误',
message: '表头重复'
});
}
},
addTr(way,index){//插入一行数据
let obj = {};
// this.tableColumns.forEach(item=>{
// obj[item.prop] = Math.floor(Math.random()*100);
// })
obj = this.getObj(this.tableColumns,obj);
console.log('obj',obj);
if(way=='top'){//在第index行之前插入一行
this.tableData.splice(index-1,0,obj);
}else{在第index行之后插入一行
this.tableData.splice(index,0,obj);
}
},
getObj(tabs,obj){
tabs.forEach(item=>{
if(item.children){
this.getObj(item.children,obj);
}else{
obj[item.prop] = Math.floor(Math.random()*100);
}
})
return obj;
},
setCurrent(row) {
this.$refs.singleTable.setCurrentRow(row);
},
handleCurrentChange(val) {//点击行事件
console.log('val',val);
this.currentRow = val;
},
}
}
</script>
<style scoped>
</style>