最近在开发的Vue项目中,使用了iview第三方UI库;对于表格组件的需求是最多的,但是在一些特定场景下,发现iview的表格组件没有单元格合并与拆分的API,搜了一下发现很多同学提问关于iview表格组件的单元格如何拆分和合并的问题。因此某家在此说下我们在项目中如何填的这个坑。
因为我们项目中首要的是单元格拆分的,因此以拆分为例。基本思路就是:不在源码层面进行修改;在外部对Table组件进行二次封装。使用vue render函数对表格组件的表格列配置数据进行动态改造,普通单元格渲染span标签呈现数据,要拆分的单元格渲染原生table标签;最后隐藏嵌套表格的边框及调整相关原生表格样式。
这里注意之前打算用iview Table组件进行嵌套,但是发现修改table组件的样式非常麻烦,而且没有效果,一不小心就容易污染全局样式,因此后来用原生table标签完美解决样式不可控问题。
1. 首先对于整体表格的列配置数据中有拆分的列进行添加split为true的属性。
2.对于表格数据源进行子表格数据定义,也就是用数组的形式包含子表格数据
3.使用vue render函数动态渲染改造表格列结构,通单元格渲染span标签呈现数据,要拆分的单元格渲染原生table标签。
let vm = this;
this.columnsList.forEach(item => {
// 可编辑单元格
if (item.editable) {
item.render = (h, param) => {
let currentRow = this.thisTableData[param.index];
if (currentRow.editting) {
// 正在编辑
if(item.split){
var childArray = currentRow[item.key];
var inputArray=[];
childArray.forEach(item => {
var aa = h('Input', {
style:{
width:'80%',
'margin-top':'10px',
'margin-bottom':'10px'
},
props: {
type: 'text',
value: item.child
},
on: {
'on-change' (event) {
let key = param.column.key;
var ddd = vm.edittingStore[param.index][key];
//item.child = event.target.value;
//计算当前的索引
var currentIndex = childArray.indexOf(item);
//更新数据
vm.edittingStore[param.index][key][currentIndex].child = event.target.value;
}
}
});
inputArray.push(aa)
var currentIndex = childArray.indexOf(item);
if(currentIndex!==childArray.length-1){
var bb = h('hr',{
style:{
height:'1px',
'background-color':'#e9eaec',
border:'none'
}
})
inputArray.push(bb)
}
})
return h('Row',inputArray)
}
else
{
return h('Input', {
style:{
width:'80%'
},
props: {
type: 'text',
value: currentRow[item.key]
},
on: {
'on-change' (event) {
let key = param.column.key;
vm.edittingStore[param.index][key] = event.target.value;
}
}
});
}
} else {
// 没在编辑
if (this.editIncell) {
// 单元格内编辑
return h('Row', {
props: {
type: 'flex',
align: 'middle',
justify: 'center'
}
}, [
h('Col', {
props: {
span: '16'
}
}, [
currentRow.edittingCell[param.column.key] ? cellInput(this, h, param, item) : h('span', currentRow[item.key])
]),
h('Col', {
props: {
span: '8'
}
}, [
currentRow.edittingCell[param.column.key] ? saveIncellEditBtn(this, h, param) : inCellEditBtn(this, h, param)
])
]);
} else {
// 非单元格内编辑
if(item.split){
if(currentRow.childProject.length==1){
var value = currentRow.childProject[0].child;
return h('span', value);
}
//用原生HTML标签渲染
var trAarry=[];
var childArray = currentRow[item.key];
childArray.forEach(item => {
var aa = h('tr',{},[
h('td',{
style:{
border:0,
'text-align':'center'
}
},item.child),
])
trAarry.push(aa)
var currentIndex = childArray.indexOf(item);
if(currentIndex!==childArray.length-1){
var bb = h('hr',{
style:{
height:'1px',
'background-color':'#e9eaec',
border:'none'
}
})
trAarry.push(bb)
}
})
return h('table',{style:{
'width':'100%',
margin:0,
border:0
}},trAarry)
}
else return h('span', currentRow[item.key]);
}
}
};
}
// 编辑和删除按钮
if (item.handle) {
item.render = (h, param) => {
let currentRowData = this.thisTableData[param.index];
let children = [];
item.handle.forEach(item => {
if (item === 'edit') {
children.push(editButton(this, h, currentRowData, param.index));
} else if (item === 'delete') {
children.push(deleteButton(this, h, currentRowData, param.index));
}
});
return h('div', children);
};
}
});
}