背景
数据为数组包对象,对象里面有属性值是数组;无需处理数据,直接使用el-table包el-table的方法,通过修改el-table的样式直接实现多行合并的效果
html代码
<template>
<div>
<el-table size="mini" :data="tableData" v-loading="ruletableLoading" border style="width: 100%" height="calc(100% - 56px)" class="rule-table">
<el-table-column label="AA" prop="code" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.code" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.code }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="BB" prop="name" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.name" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="CC">
<template #default="scope">
<el-table :data="scope.row.items" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="name" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.name" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.name }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="DD" width="120">
<template #default="scope">
<el-table :data="scope.row.items" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="percent" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.percent" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.percent }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="EE" width="120">
<template #default="scope">
<el-table :data="scope.row.items" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="score" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.score" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.score }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="FF" prop="totalScore" show-overflow-tooltip width="120">
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.totalScore" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.totalScore }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="GG">
<template #default="scope">
<el-table :data="scope.row.classStandard" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="express" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.express" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.express }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="HH">
<template #default="scope">
<el-table :data="scope.row.classStandard" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="class" show-overflow-tooltip>
<template #default="scope">
<!-- <div class="item"> -->
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.class" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.class }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="II">
<template #default="scope">
<el-table :data="scope.row.classStandard" :border="false" :show-header="false" class="no-border-table">
<el-table-column prop="remark" show-overflow-tooltip>
<template #default="scope">
<div class="cell-content item-normal" @click.stop="cellClick">
<el-input size="small" class="item__input" v-model="scope.row.remark" placeholder="请输入" @blur="handleBlur"></el-input>
<div class="item__txt">{{ scope.row.remark }}</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
</el-table>
</div>
</template>
js代码
主要是cellClick和handleBlur控制的,首先需要找到包裹el-input和展示表格文字的父div,然后通过点击父div和el-input的失去焦点事件控制内部这两个元素的显示和隐藏
<script setup>
import { ref, computed,onMounted } from 'vue'
import ruletableDataJson from './ruleManage.json'
import { cloneDeep } from 'lodash'
const tableData=ref([])
onMounted(()=>{
tableData.value=[
{
"id": 9090,
"code": "1",
"name": "密码和车好多看",
"remark": "",
"items": [
{
"id": 6767,
"name": "合适的客户收款",
"percent": 0.7,
"score": 100
},
{
"id": 89808,
"name": "附近的看法好的",
"percent": 0.3,
"score": 67
}
],
"classStandard": [
{
"express": "年卡就诊卡",
"remark": "活动开始计划的卡号",
"class": "打开了电视机了"
},
{
"express": "手机多少空间",
"remark": "简单说来就是了",
"class": "的"
},
{
"express": "的角度来讲罗迪克",
"remark": "十九岁的离开拘留所",
"class": "对手的实力的距离"
},
{
"express": "但是肯定是咯",
"remark": "发达的",
"class": "人工费v1"
},
{
"express": "的快捷键",
"remark": "附近的垃圾分类",
"class": "分隔符"
},
{
"express": "三大三",
"remark": "反对反对开始",
"class": "对顶的"
},
{
"express": "多睡的",
"remark": "对顶的",
"class": "对对对对"
},
{
"express": "对顶的",
"remark": "的舒适性",
"class": "多睡的"
},
{
"express": "是啥",
"remark": "都是大客户",
"class": "山东江苏科技"
}
]
},
{
"id": 9090,
"code": "2",
"name": "密码和车好多看",
"remark": "",
"items": [
{
"id": 6767,
"name": "合适的客户收款",
"percent": 0.7,
"score": 100
},
{
"id": 89808,
"name": "附近的看法好的",
"percent": 0.3,
"score": 67
}
],
"classStandard": [
{
"express": "年卡就诊卡",
"remark": "活动开始计划的卡号",
"class": "打开了电视机了"
},
{
"express": "手机多少空间",
"remark": "简单说来就是了",
"class": "的"
},
{
"express": "的角度来讲罗迪克",
"remark": "十九岁的离开拘留所",
"class": "对手的实力的距离"
},
{
"express": "但是肯定是咯",
"remark": "发达的",
"class": "人工费v1"
},
{
"express": "的快捷键",
"remark": "附近的垃圾分类",
"class": "分隔符"
},
{
"express": "三大三",
"remark": "反对反对开始",
"class": "对顶的"
},
{
"express": "多睡的",
"remark": "对顶的",
"class": "对对对对"
},
{
"express": "对顶的",
"remark": "的舒适性",
"class": "多睡的"
},
{
"express": "是啥",
"remark": "都是大客户",
"class": "山东江苏科技"
}
]
},
{
"id": 9090,
"code": "3",
"name": "密码和车好多看",
"remark": "",
"items": [
{
"id": 6767,
"name": "合适的客户收款",
"percent": 0.7,
"score": 100
},
{
"id": 89808,
"name": "附近的看法好的",
"percent": 0.3,
"score": 67
}
],
"classStandard": [
{
"express": "年卡就诊卡",
"remark": "活动开始计划的卡号",
"class": "打开了电视机了"
},
{
"express": "手机多少空间",
"remark": "简单说来就是了",
"class": "的"
},
{
"express": "的角度来讲罗迪克",
"remark": "十九岁的离开拘留所",
"class": "对手的实力的距离"
},
{
"express": "但是肯定是咯",
"remark": "发达的",
"class": "人工费v1"
},
{
"express": "的快捷键",
"remark": "附近的垃圾分类",
"class": "分隔符"
},
{
"express": "三大三",
"remark": "反对反对开始",
"class": "对顶的"
},
{
"express": "多睡的",
"remark": "对顶的",
"class": "对对对对"
},
{
"express": "对顶的",
"remark": "的舒适性",
"class": "多睡的"
},
{
"express": "是啥",
"remark": "都是大客户",
"class": "山东江苏科技"
}
]
},
]
})
const cellClick = e => {
let element = e.target.parentNode
element.classList.remove('item-normal')
element.classList.add('item-edit')
}
const handleBlur = e => {
let element = e.target.parentNode.parentNode
element.classList.remove('item-edit')
element.classList.add('item-normal')
dotShow.value=true
}
</script>
scss样式
首先设置cell-content的基础样式;元素饿显示和隐藏就单独拿出来通过在事件中做切换
<style lang='scss' scoped>
// 对elementplus的样式修改
.rule-table:deep() .cell {
padding-left: 0px;
padding-right: 0px;
}
:deep(.el-table--border) {
border: none;
}
.rule-table .no-border-table :deep()tr:last-child td {
border-bottom: none;
}
:deep().el-table::before {
width: 0%;
height: 0px;
}
.rule-table .no-border-table :deep()th {
border-right: none;
}
.rule-table .no-border-table :deep()td {
border-right: none;
}
// 可编辑
.cell-content {
cursor: pointer;
.item__input {
// display: none;
width: 95%;
/* 调整elementUI中样式 如果不需要调整请忽略 */
.el-input__inner {
height: 24px !important;
}
/* 调整elementUI中样式 如果不需要调整请忽略 */
.el-input__suffix {
i {
font-size: 12px !important;
line-height: 26px !important;
}
}
}
.item__txt {
// display: block;
box-sizing: border-box;
line-height: 32px;
padding: 0 9px;
}
}
// 单独设置编辑状态和常规状态
.item-edit {
.item__input {
display: block;
}
.item__txt {
display: none;
}
}
.item-normal {
.item__input {
display: none;
}
.item__txt {
display: block;
}
}
</style>