combinación dinámica de filas de la tabla antd
efecto de fusión
método de paso
1. Calcule dinámicamente la cantidad de filas que se fusionarán cada vez en el nodo calculado
computed: {
columns() {
return [
{
title: "区域",
dataIndex: "area",
customRender: (text, row, index) => {
const obj = {
children: text !== null ? text : "",
attrs: {
rowSpan: 1,
},
};
obj.attrs.rowSpan = this.renderCells(text, this.currentTable, "area",index);
return obj;
},
},
{
title: "名称",
dataIndex: "name",
},
{
title: "数量",
dataIndex: "count",
},
{
title: "进度",
dataIndex: "progress",
},
];
},
}
2. Defina el método de combinación de celdas en el nodo de métodos
renderCells(text, data, key, index) {
if (data.length < 1) {
return 1;
}
if (text === "" || text === null) {
data[index].rowNum = 1;
return 1;
}
// 上一行该列数据是否一样
if (index !== 0 && text === data[index - 1][key] && index % this.pagination.pageSize != 0) {
data[index].rowNum = 0;
return 0;
}
let rowSpan = 1;
// 判断下一行是否相等
for (let i = index + 1; i < data.length; i++) {
if (text !== data[i][key]) {
break;
}
rowSpan++;
}
data[index].rowNum = rowSpan;
return rowSpan;
}
3. Si desea obtener todos los datos a la vez para la paginación, debe modificarlos al calcular las columnas.
columns() {
return [
{
title: "区域",
dataIndex: "area",
customRender: (text, row, index) => {
const obj = {
children: text !== null ? text : "",
attrs: {
rowSpan: 1,
},
};
obj.attrs.rowSpan = this.renderCells(text, this.currentTable, "area", Number(index)+Number(this.pagination.pageSize * (this.pagination.current - 1)));
return obj;
},
},
{
title: "名称",
dataIndex: "name",
},
{
title: "数量",
dataIndex: "count",
},
{
title: "进度",
dataIndex: "progress",
},
];
},
Artículo de referencia: fusión de forma dinámica de ant design vue
efecto de fusión
Si queremos fusionar con la misma columna de nombre, debemos modificar el código original. La premisa de la fusión es que las regiones son las mismas y los nombres son los mismos. Solo necesitamos agregar una capa de juicio al calcular el número de filas fusionadas.
renderCells(text, data, key, index) {
if (data.length < 1) {
return 1;
}
if (text === "" || text === null) {
data[index].rowNum = 1;
return 1;
}
// 上一行该列数据是否一样
if (index !== 0 && text === data[index - 1][key] && index % this.pagination.pageSize != 0) {
if(key === 'name'){
if(data[index-1]['area'] === data[index]['area']){
data[index].rowNum = 0
return 0;
}
}else{
data[index].rowNum = 0;
return 0;
}
}
let rowSpan = 1;
// 判断下一行是否相等
for (let i = index + 1; i < data.length; i++) {
if(key === 'name' && data[i]['area'] !== data[index]['area']){
break;
}
if (text !== data[i][key] ) {
break;
}
rowSpan++;
}
data[index].rowNum = rowSpan;
return rowSpan;
},
celda editable
líneas no fusionadas
Puede consultar la celda editable oficial de ant-design-vue, el ejemplo oficial es el siguiente:
<template>
<div>
<a-button class="editable-add-btn" @click="handleAdd">
Add
</a-button>
<a-table bordered :data-source="dataSource" :columns="columns">
<template slot="name" slot-scope="text, record">
<editable-cell :text="text" @change="onCellChange(record.key, 'name', $event)" />
</template>
<template slot="operation" slot-scope="text, record">
<a-popconfirm
v-if="dataSource.length"
title="Sure to delete?"
@confirm="() => onDelete(record.key)"
>
<a href="javascript:;">Delete</a>
</a-popconfirm>
</template>
</a-table>
</div>
</template>
<script>
const EditableCell = {
template: `
<div class="editable-cell">
<div v-if="editable" class="editable-cell-input-wrapper">
<a-input :value="value" @change="handleChange" @pressEnter="check" /><a-icon
type="check"
class="editable-cell-icon-check"
@click="check"
/>
</div>
<div v-else class="editable-cell-text-wrapper">
{
{ value || ' ' }}
<a-icon type="edit" class="editable-cell-icon" @click="edit" />
</div>
</div>
`,
props: {
text: String,
},
data() {
return {
value: this.text,
editable: false,
};
},
methods: {
handleChange(e) {
const value = e.target.value;
this.value = value;
},
check() {
this.editable = false;
this.$emit('change', this.value);
},
edit() {
this.editable = true;
},
},
};
export default {
components: {
EditableCell,
},
data() {
return {
dataSource: [
{
key: '0',
name: 'Edward King 0',
age: '32',
address: 'London, Park Lane no. 0',
},
{
key: '1',
name: 'Edward King 1',
age: '32',
address: 'London, Park Lane no. 1',
},
],
count: 2,
columns: [
{
title: 'name',
dataIndex: 'name',
width: '30%',
scopedSlots: {
customRender: 'name' },
},
{
title: 'age',
dataIndex: 'age',
},
{
title: 'address',
dataIndex: 'address',
},
{
title: 'operation',
dataIndex: 'operation',
scopedSlots: {
customRender: 'operation' },
},
],
};
},
methods: {
onCellChange(key, dataIndex, value) {
const dataSource = [...this.dataSource];
const target = dataSource.find(item => item.key === key);
if (target) {
target[dataIndex] = value;
this.dataSource = dataSource;
}
},
onDelete(key) {
const dataSource = [...this.dataSource];
this.dataSource = dataSource.filter(item => item.key !== key);
},
handleAdd() {
const {
count, dataSource } = this;
const newData = {
key: count,
name: `Edward King ${
count}`,
age: 32,
address: `London, Park Lane no. ${
count}`,
};
this.dataSource = [...dataSource, newData];
this.count = count + 1;
},
},
};
</script>
Combinar dinámicamente celdas editables
En el proceso de aplicación real, puede encontrarse con la necesidad de fusionar dinámicamente celdas editables. Se sabe que scopedSlots puede ayudarnos a editar celdas, y customRender puede personalizar celdas combinadas dinámicas. Pero después de la práctica, se descubre que los dos no se pueden usar al mismo tiempo. Refiriéndose a la solución de fusionar dinámicamente celdas editables en la tabla ant-design-vue, se encuentra que el conflicto entre scopedSlots y customRender se puede resolver a través de la sintaxis JSX
computed: {
columns() {
return [
{
title: "区域",
dataIndex: "area",
scopedSlots: {
customRender: 'area' },
customRender: (text, row, index) => {
const obj = {
children: <editable-cell text={
text} onChange={
(val) => this.onCellChange(row.id,'area',val)}></editable-cell>,
attrs: {
rowSpan: 1,
},
};
obj.attrs.rowSpan = this.mergeCells(text, this.currentTable, "area", Number(index)+Number(this.pagination.pageSize * (this.pagination.current - 1)));
return obj;
},
},
{
title: "名称",
dataIndex: "name",
},
{
title: "数量",
dataIndex: "count",
},
{
title: "进度",
dataIndex: "progress",
},
];
},
},