功能简介
场景
需要一个单击即可编辑的可编辑表格组件,要求能自定义组件项目,表格可以扩展操作栏,下拉框,多选框等功能
实现
通过div+antd实现可编辑表格组件(ps:难点在于用css处理每个dom节点之间的边),表格由配置项生成。
表格配置项结构:
入参 | 作用 |
---|---|
key | 绑定字段 |
title | 表头显示参数 |
type | 类型(input:输入框,select:下拉框,checkbox:单选框,operation:按钮组) |
width | 单元格宽度 |
align | 文字位置 |
rowColumns | 用于除输入框以外其他类型自定义使用 |
基于此配置项达成我所想要的自定义表格,功能不全面,后续大家可以按照自己所需调整优化即可。
代码实现
父组件
<template>
<div style="width: 100wh;padding: 24px;">
<edit-table :data="table.data" :columns="table.columns" :width="1110" size="large" :height="300" @delete="deleteData" @alert="alertData"></edit-table>
</div>
</template>
<script>
import EditTable from '@/components/EditTable.vue'
export default {
components: {
EditTable
},
data() {
return {
table: {
data: [],
// title:表头显示,key:绑定字段,type: 类型 ,width:表格宽度,align:文字位置,rowColumns:专用于除了输入框类型外的附属字段(非必填)
columns: [{
title: '姓名',
key: 'name',
type: 'input',
width: '150px',
align: 'center'
},
{
title: '性别',
key: 'sex',
type: 'select',
rowColumns: [{
value: 'man',
label: '男'
},
{
value: 'woman',
label: '女'
}
],
width: '60px',
align: 'center'
},
{
title: '年龄',
key: 'age',
type: 'input',
width: '100px',
align: 'center'
},
{
title: '其他信息',
key: 'single',
type: 'checkbox',
width: '300px',
rowColumns:[
{
value: 'single',
label: '独生子女'
},
{
value: 'married',
label: '已婚'
}
],
align: 'center'
},
{
title: '备注',
key: 'remark',
type: 'input',
width: '300px',
align: 'center'
},
{
title: '操作',
key: 'op',
type: 'operation',
width: '200px',
align: 'center',
rowColumns:[
{
value: 'alert',
label: '展示',
style:{
'margin-right':'12px',
'background-color':'#1890ff',
color:'#ffffff',
'font-size':'12px'
}
},
{
value: 'delete',
label: '删除',
style:{
'background-color':'#ff000099',
color:'#ffffff',
'font-size':'12px'
}
}
],
}
]
}
}
},
created(){
this.table.data = [
{
name: '张三',
sex: 'man',
age: '21',
single: true,
married:false,
remark: '这是一条关于张三的备注'
},
{
name: '李四',
sex: 'man',
age: '56',
single: false,
married:true,
remark: '这是一条关于李四的备注'
},
{
name: '王五',
sex: 'woman',
age: '37',
single: false,
married:true,
remark: '这是一条关于王五的备注'
},
{
name: '赵六',
sex: 'woman',
age: '40',
single: false,
married:true,
remark: '这是一条关于赵六的备注'
},
{
name: '麻子',
sex: 'man',
age: '120',
single: false,
married:true,
remark: '这是一条关于麻子的备注'
},
{
name: '老K',
sex: 'man',
age: '6',
single: true,
married:false,
remark: '这是一条关于老K的备注'
}
]
},
methods:{
deleteData(row,index){
console.log(row)
this.table.data.splice(index,1)
},
alertData(row,index){
this.$message.info(`您选中的数据为:姓名:${row.name},性别:${row.sex},年龄:${row.age},${row.single?'为独生子女':'不为独生子女'},${row.married?'已婚':'未婚'}`)
}
}
}
</script>
<style lang="less" scoped>
</style>
子组件(表格组件)
<template>
<div class="edit-table-page" :style="{width:`${width + 20}px`}">
<!-- 表头 -->
<div class="page-header" :style="{height:sizeList[size],'line-height':sizeList[size]}">
<div class="page-header-div" v-for="(item,index) in columns" :key="index" :style="{width:item.width?item.width:'10%','text-align':item.align?item.align:'left'}">
{{item.title}}
</div>
</div>
<div class="page-body">
<div class="page-body-noEmpty" v-if="data.length" :style="{height:`${height}px`}">
<div v-for="(row,index) in data" :key="index" class="page-body-div" :style="{height:sizeList[size],'line-height':sizeList[size]}">
<div v-for="(item,i) in columns" :key="i" class="body-div-row" :style="{width:item.width?item.width:'10%'}">
<!-- 输入框 -->
<a-input v-if="item.type==='input'" v-model="row[item.key]" :style="{'text-align':item.align?item.align:'left'}"></a-input>
<!-- 下拉框 -->
<a-select v-else-if="item.type==='select'" v-model="row[item.key]">
<a-select-option v-for="selectItem in item.rowColumns" :key="selectItem.value">
{{selectItem.label}}
</a-select-option>
</a-select>
<!-- 选择框 -->
<div v-else-if="item.type==='checkbox'" class="table-checkbox-group" :style="{'justify-content':item.align?alignList[item.align]:'start'}">
<a-checkbox v-for="(checkboxItem,checkboxIndex) in item.rowColumns" :key="checkboxIndex" :checked="row[checkboxItem.value]" @change="checkBoxChange($event,index,checkboxItem.value)">{{checkboxItem.label}}</a-checkbox>
</div>
<!-- 操作栏 -->
<div v-else-if="item.type==='operation'" class="table-checkbox-group" :style="{'justify-content':item.align?alignList[item.align]:'start'}">
<a-button v-for="(buttonItem,buttonIndex) in item.rowColumns" :style="buttonItem.style" size="small" :key="buttonIndex" @click="operationButtonClick(index,buttonItem.value)">{{buttonItem.label}}</a-button>
</div>
</div>
</div>
</div>
<div class="page-body-empty" v-else>
暂无数据
</div>
</div>
</div>
</template>
<script>
export default {
name: 'EditTable',
props: {
//表格数据
data: {
type: Array
},
//表格头配置项
columns: {
type: Array
},
width: {
type: Number,
default: () => 1000
},
size:{
type: String,
default: () => 'default'
},
height:{
type: Number,
default: () => 300
}
},
data() {
return {
// 表格大小转译字典
sizeList: {
large: '40px',
default: '32px',
small: '24px'
},
// 布局转译
alignList:{
left:'start',
center:'center',
right:'end',
}
}
},
methods:{
// 选择框选择切换事件
checkBoxChange(event,index,key){
this.data[index][key] = event.target.checked
},
// 点击事件外抛
operationButtonClick(index,value){
this.$emit(value,this.data[index],index)
}
}
}
</script>
<style lang="less" scoped>
//表格主体
.edit-table-page {
margin: auto;
border: 1px solid #E1E2E3;
border-bottom: 0;
//表格头部
.page-header {
border-bottom: 1px solid #E1E2E3;
width: 100%;
.page-header-div {
display: inline-block;
border-right: 1px solid #E1E2E3;
overflow: hidden;
&:last-child {
border-right: 0px;
}
}
}
//表格主体
.page-body {
//有数据
.page-body-noEmpty {
overflow: auto;
width: 100%;
border-bottom: 1px solid #E1E2E3;
.page-body-div {
border-bottom: 1px solid #E1E2E3;
.body-div-row {
display: inline-block;
height: calc(100% - 1px);
border-right: 1px solid #E1E2E3;
&:last-child {
border-right: 0px;
}
//击穿样式
/deep/ .ant-input {
vertical-align: top;
width: 100%;
border: 0px;
border-radius: 0px;
height: 100%;
&:hover {
border: 0px;
border: 1px solid #4787f0;
}
&:focus {
border: 1px solid #1890ff;
box-shadow: none;
}
}
/deep/ .ant-select{
vertical-align: top;
width: 100%;
height: 100%;
&:hover {
border: 0px;
border: 1px solid #4787f0;
}
&:focus {
border: 1px solid #1890ff;
box-shadow: none;
}
.ant-select-selection{
height: calc(100% - 1px);
border: 0px;
border-radius: 0px;
}
}
.table-checkbox-group{
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
}
}
}
//无数据
.page-body-empty {
height: 300px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
border-bottom: 1px solid #E1E2E3;
}
}
}
</style>
效果展示
图1
图2
图3
视频介绍
可编辑表格组件介绍