效果
核心
布局配置矩阵(以下为多个模式),可以使用|
或\n
表示矩阵行
const gridArr = [
`
1,2,a,b
3,4,a,b
5,6,a,b
`,
`
1,2
3,4
5,6
`,
`
1,2,3,4
3,4
`
]
任意横向或者纵向相同的字符表示一个合并块
使用
<CalcTable grid="1,2,a,b|3,4,a,b|5,6,a,b" >
<span>姓名</span>
<span>李牧</span>
<span>证件</span>
<span>img</span>
<span>性别</span>
<span>男</span>
<span>身份证号</span>
<span>3707783199609282223</span>
</CalcTable>
代码
因为是在vue开发中有些地方使用表格布局,后来想偷懒不写tr,td,然后就有了以下代码,可扩展为组件化的任意布局方案管理
<script>
/*
* 通过输入表格标记矩阵自动生成合并后的表格结构
*
* 可扩展为组件化的任意布局
* */
export default {
name: "CalcTable",
data() {
return {
}
},
props: {
grid: {
type: String,
default: '1,2,3,4|5,5,3,4|5,5,6,7|8,9,10,1|7,9,1,2'
}
},
render(h) {
const vm = this
const innerVNode = vm.$scopedSlots.default()
let renderIndex = 0
//1)计算matrix
const matrix = vm.gridStrToMatrix()
//2)双层循环遍历matrix,及逐行逐列
return h('table', {}, matrix.map(row => {
return h('tr',
{},
[
h('td',{
class:{
fill:true
}
}),
row.filter(d => d).map(cell => {
return h('td', {
attrs: {
colspan: cell[1],
rowspan: cell[0]
}
}, renderIndex<innerVNode.length ? [innerVNode[renderIndex++]] : [])
})
])
}))
},
methods: {
gridStrToMatrix() {
const vm = this
//以行列表示每个字符位置
let rows = vm.grid.replace(/ /g,'').split(/\n|\|/).filter(d=>d)
let matrix = new Array(rows.length)
rows.forEach((row, index) => {
matrix[index] = row.split(',')
})
//遍历所有进行合并标记
let rowIndex, colIndex, row, cell
for (rowIndex = 0; rowIndex < matrix.length; rowIndex++) {
row = matrix[rowIndex]
for (colIndex = 0; colIndex < row.length; colIndex++) {
cell = matrix[rowIndex][colIndex]
// console.log(cell)
if (cell != null) {
let span = [1, 0]
for (let i = colIndex; i < row.length; i++) {
if (row[i] == cell) {
span[1]++
row[i] = null
}
}
for (let i = rowIndex; i < matrix.length; i++) {
if (matrix[i][colIndex] == cell) {
span[0]++
matrix[i][colIndex] = null
}
}
for (let i = rowIndex; i < rowIndex + span[0]; i++) {
for (let j = colIndex; j < colIndex + span[1]; j++) {
matrix[i][j] = null
}
}
matrix[rowIndex][colIndex] = span
}
}
}
return matrix
}
}
}
</script>
<style scoped>
td {
border: 1px solid #000;
padding: 20px;
}
table {
border-collapse: collapse;
}
.fill {
padding-left: 0;
padding-right: 0;
border: 0;
}
</style>