【业务实战】ant design + css3 编写方便使用的可编辑表格组件

【业务实战】vue + ant design + css3 编写快速可编辑表格组件

功能简介

场景

需要一个单击即可编辑的可编辑表格组件,要求能自定义组件项目,表格可以扩展操作栏,下拉框,多选框等功能

实现

通过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
事件交互

视频介绍

可编辑表格组件介绍

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值