ElementUI table+dialog实现一个简单的可编辑的表格

table组件如何实现可编辑呢?

我的需求是把table组件那样的表格,实现它点击可以弹出一个框,然后在这个框里面输入你的东西,然后将他回显回去,当然,输入的有可能是时间啥的。

为什么要弹出弹层不在框上直接编辑呢?因为框太小了,用户可能看不见输入的是啥。

我们可以利用element组件的插槽,获取数值,然后回显到表格里。

HTML部分

我用了一个弹层来写这个功能,如果测试效果,可以直接在主页面引入 ,将弹层的控制开关改为true。

<template>
	<el-drawer v-model="drawerVisible" size="calc(100% - 210px)" @close="resetForm">
		<el-container>
			<el-form ref="ruleFormRef2" label-position="right" :model="form" label-width="138px">
				<div class="form-left">
					<div class="sepcial_about">
						<div class="tableForm">
							<el-table :data="testDatas" border style="width: 700px">
								<el-table-column v-for="(col, idx) in columnList" :key="col.prop" :index="idx" :width="idx === 1 ? '180px' : ''">
									<template #header>
										<p>
											{{ col.label }}
										</p>
									</template>
									<template #default="{ row }">
										<p :class="col.prop == 'remark' ? 'p_remark' : 'p1111'" @click="e => handleEdit(0, row, col)">
											{{ col.prop == "time" ? changeTime(row[col.prop]) : row[col.prop] }}
										</p>
									</template>
								</el-table-column>
								<el-table-column width="120">
									<template #header>
										<p class="p_specail">操作</p>
									</template>
									<template #default="scope">
										<p class="p1111">
											<el-button link type="primary" size="large" @click.prevent="delRow(scope, 0)">删除</el-button>
										</p>
									</template>
								</el-table-column>
							</el-table>
							<el-button type="primary" class="mt-4" style="width: 100%" @click="addRow(0)">新增</el-button>
						</div>
					</div>
				</div>
			</el-form>
			<el-dialog v-model="dialogVisible" title="添加" width="30%" center align-center>
				<span>{{ sureMsg }}</span>
				<template #footer>
					<span class="dialog-footer">
						<el-button type="primary" @click="toSure">确 认</el-button>
					</span>
				</template>
			</el-dialog>
			<el-dialog v-model="addDialog" :title="addTitle" width="30%" center align-center>
				<el-date-picker v-if="isTime" v-model="addinput" type="daterange" format="YYYY/MM/DD" value-format="YYYY-MM-DD" />
				<el-input
					v-if="isNum"
					resize="none"
					maxlength="15"
					show-word-limit
					v-model="addinput"
					type="textarea"
					size="large"
					placeholder="请输入"
				/>
				<el-input
					v-if="!isNum && !isTime"
					resize="none"
					maxlength="500"
					show-word-limit
					v-model="addinput"
					type="textarea"
					size="large"
					placeholder="请输入"
				/>
				<template #footer>
					<span class="dialog-footer">
						<el-button type="primary" @click="sava">保存</el-button>
					</span>
				</template>
			</el-dialog>
		</el-container>
	</el-drawer>
</template>

JS

1.渲染数据集合

自定义的表头,HTML结构中通过v-for 循环表头列表,进行label的取值来构建最基础的表格

// 表格之中的数据
const testDatas: any = ref([]);

// 表头列表
const columnList: any = ref([
	{ prop: "projectName", label: "测试1" },
	{ prop: "time", label: "时间段" },
	{ prop: "projectContentSummary", label: "测试2" }
]);

2.handleEdit函数

这个函数主要是用来控制弹层的弹出,通过行的标签名字判断需要什么输入的值。根据whatSava的值来判断你点击的是哪个表格,这个参数在HTML结构写死,cellRow和cellCol就是在渲染的时候带入的行的值和列的值。可以获得标签名字或者prop字段用来做判断。当然,这些名字也可以用来设置弹出弹框的弹框名字。

然后判断prop的值来看是不是需要输入 或者是 时间段格式的,让各自的开关变为true或者false

并且根据cellRow[cellCol.prop]这个值来对弹出来的框进行赋值,也就是回显。

const addinput = ref("");
const addTitle = ref("");
const addCode = ref();
const addProp = ref();
const isTime = ref(false);
const savaWhat = ref();
const isNum = ref(false);
const handleEdit = (whatSava: any, cellRow: any, cellCol: any) => {
	if (whatSava == "0") {
		savaWhat.value = 0;
	}
	if (cellCol.prop == "ceshi1" || cellCol.prop == "ceshi2") {
		isTime.value = false;
		if (cellCol.prop == "ceshi2") {
			isNum.value = true;
		} else {
			isNum.value = false;
		}
		addTitle.value = cellCol.label;
		addProp.value = cellCol.prop;
		addCode.value = cellRow.index;
		addinput.value = cellRow[cellCol.prop];
		addDialog.value = true;
	} else {
		isTime.value = true;
		addTitle.value = cellCol.label;
		addProp.value = cellCol.prop;
		addCode.value = cellRow.index;
		addinput.value = cellRow[cellCol.prop];
		addDialog.value = true;
	}
};

3.保存弹框函数

这个函数就是弹出层的保存函数,先找到你点击的是哪个框,然后把弹框里面输入的东西赋值给他,如果是数字的话,就用正则限制一下,不让他输入数字以外的东西。最后要清空一下,防止下次回显。

const sava = () => {
	let idx = testDatas.value.findIndex((p: any) => p.index == addCode.value);
	if (addProp.value == "ceshi2") {
		if (!/^[0-9]*$/.test(addinput.value)) {
			ElMessage.warning("请输入数字");
			return;
		}
		testDatas.value[idx][addProp.value] = addinput.value;
	} else {
		testDatas.value[idx][addProp.value] = addinput.value;
	}
	addinput.value = "";
	addDialog.value = false;
};

4.清洗时间格式函数

因为我们日期时间选择器,得到的是一个数组,所以我们回显的时候,应该拿数组的第一项和第二项,然后拼接起来,得到我们回显的正确格式。

//时间格式清洗
const changeTime = (data: any) => {
	if (!data) {
		return "";
	} else {
		let data1 = data[0] + "~" + data[1];
		return data1;
	}
};

5.添加函数

只需要我们知道添加的是哪个表格的,单表格就可以忽略whatAdd这个参数。

逻辑就是先判断他是不是为空,为空的话给他单纯的加一行,不为空的话,得到数组的长度,给他加一个index,我在写的过程中,发现我们没有办法获得一个标识,所以我写了一个index来当作唯一标识,当然,这个在获取后端接口的时候,需要你获取后端给你数组的长度,然后再依次相加就不会导致错误的出现。

// 添加一行
const addRow = (whatAdd: number) => {
	if (whatAdd == 0) {
		let obj: any = {};
		if (testDatas.value.length == 0) {
			obj.index = "0";
			columnList.value.forEach((p: any) => {
				obj[p.prop] = "";
			});
			testDatas.value[0] = obj;
		} else {
			const weiyi = testDatas.value[testDatas.value.length - 1].index;
			columnList.value.forEach((p: any) => {
				obj[p.prop] = "";
			});
			obj.index = String(Number(weiyi) + 1);
			testDatas.value[testDatas.value.length] = obj;
		}
	}
};

6.删除函数

因为删除标签在table表格之中,所以我们可以用scope准确的获得是哪一行,然后用whatDel判断你删除的是哪个表格。

//删除
const delRow = (scope: any, whatDel: number) => {
	const arrIndex = scope.$index; //唯一标识
	//将testDatas中的第arrIndex项数据删除
	if (whatDel == 0) {
		testDatas.value.splice(arrIndex, 1);
	}
};

CSS

<style scoped lang="scss">
:deep(.el-textarea__inner) {
	height: 200px;
}
:deep(.cell) {
	text-align: center !important;
	height: 45px;
	padding: 0;
}
.p1111 {
	height: 50px;
	line-height: 50px !important;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	padding: 0;
	margin: 0;
	text-align: center !important;
}

.tableForm {
	width: 700px;
	margin-left: 35px;
	margin-top: 20px;
}
.sepcial_about {
	width: 500px;
	padding-left: 40px;
	box-sizing: border-box;
	margin-bottom: 60px;
	position: relative;

	> :first-child {
		width: 1000px;
		margin-bottom: 10px;
	}
}
.sepcial_about .mt-4 {
	position: absolute;
	width: 40px !important;
	height: 30px !important;
	bottom: 10px;
	left: 800px;
	z-index: 999;
}
.sepcial_about :deep(.el-table) {
	display: block;
	height: 100%;
}
:deep(.el-date-editor) {
	width: 100% !important;
	height: 50px;
	text-align: center;
}




.form-left {
	padding-top: 20px;
}


:deep(.el-form-item__content) {
	/* margin-top: 20px; */
	margin-left: 40px !important;
}



:deep(.el-form-item__label) {
	font-size: 16px;
	color: black;
}
</style>

 全部代码

<template>
	<el-drawer v-model="drawerVisible" size="calc(100% - 210px)" @close="resetForm">
		<el-container>
			<el-form ref="ruleFormRef2" label-position="right" :model="form" label-width="138px">
				<div class="form-left">
					<div class="sepcial_about">
						<div class="tableForm">
							<el-table :data="testDatas" border style="width: 700px">
								<el-table-column v-for="(col, idx) in columnList" :key="col.prop" :index="idx" :width="idx === 1 ? '180px' : ''">
									<template #header>
										<p>
											{{ col.label }}
										</p>
									</template>
									<template #default="{ row }">
										<p :class="col.prop == 'remark' ? 'p_remark' : 'p1111'" @click="e => handleEdit(0, row, col)">
											{{ col.prop == "time" ? changeTime(row[col.prop]) : row[col.prop] }}
										</p>
									</template>
								</el-table-column>
								<el-table-column width="120">
									<template #header>
										<p class="p_specail">操作</p>
									</template>
									<template #default="scope">
										<p class="p1111">
											<el-button link type="primary" size="large" @click.prevent="delRow(scope, 0)">删除</el-button>
										</p>
									</template>
								</el-table-column>
							</el-table>
							<el-button type="primary" class="mt-4" style="width: 100%" @click="addRow(0)">新增</el-button>
						</div>
					</div>
				</div>
			</el-form>
			<el-dialog v-model="addDialog" :title="addTitle" width="30%" center align-center>
				<el-date-picker v-if="isTime" v-model="addinput" type="daterange" format="YYYY/MM/DD" value-format="YYYY-MM-DD" />
				<el-input
					v-if="isNum"
					resize="none"
					maxlength="15"
					show-word-limit
					v-model="addinput"
					type="textarea"
					size="large"
					placeholder="请输入"
				/>
				<el-input
					v-if="!isNum && !isTime"
					resize="none"
					maxlength="500"
					show-word-limit
					v-model="addinput"
					type="textarea"
					size="large"
					placeholder="请输入"
				/>
				<template #footer>
					<span class="dialog-footer">
						<el-button type="primary" @click="sava">保存</el-button>
					</span>
				</template>
			</el-dialog>
		</el-container>
	</el-drawer>
</template>

<script setup lang="tsx" name="addConfig">
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
const drawerVisible = ref(false);
const addDialog = ref(false);
const addinput = ref("");
const testDatas: any = ref([]);
const columnList: any = ref([
	{ prop: "ceshi1", label: "测试1" },
	{ prop: "time", label: "时间段" },
	{ prop: "ceshi2", label: "测试2" }
]);
const addTitle = ref("");
const addCode = ref();
const addProp = ref();
const isTime = ref(false);
const savaWhat = ref();
const isNum = ref(false);
const handleEdit = (whatSava: any, cellRow: any, cellCol: any) => {
	if (whatSava == "0") {
		savaWhat.value = 0;
	}
	if (cellCol.prop == "ceshi1" || cellCol.prop == "ceshi2") {
		isTime.value = false;
		if (cellCol.prop == "ceshi2") {
			isNum.value = true;
		} else {
			isNum.value = false;
		}
		addTitle.value = cellCol.label;
		addProp.value = cellCol.prop;
		addCode.value = cellRow.index;
		addinput.value = cellRow[cellCol.prop];
		addDialog.value = true;
	} else {
		isTime.value = true;
		addTitle.value = cellCol.label;
		addProp.value = cellCol.prop;
		addCode.value = cellRow.index;
		addinput.value = cellRow[cellCol.prop];
		addDialog.value = true;
	}
};
const sava = () => {
	let idx = testDatas.value.findIndex((p: any) => p.index == addCode.value);
	if (addProp.value == "ceshi2") {
		if (!/^[0-9]*$/.test(addinput.value)) {
			ElMessage.warning("请输入数字");
			return;
		}
		testDatas.value[idx][addProp.value] = addinput.value;
	} else {
		testDatas.value[idx][addProp.value] = addinput.value;
	}
	addinput.value = "";
	addDialog.value = false;
};
let form: any = reactive({});
//时间格式清洗
const changeTime = (data: any) => {
	if (!data) {
		return "";
	} else {
		let data1 = data[0] + "~" + data[1];
		return data1;
	}
};
//清空数据
const resetForm = () => {
	form.companyName = "";
	form.linkman = "";
	form.companyType = "";
	form.contactTitle = "";
	form.contactPhone = "";
	form.id1 = [];
	form.id2 = [];
	form.idCardPhoto = [];
	form.publicCreditInformationReportOfEnterpriseInstitutions = [];
	form.businessLicenseOrLegalRepresentativeCertificate = [];
	form.lastYearBankCertificationDocuments = [];
	form.taxPaymentMaterialsForThePastYear = [];
	form.employeePaymentCertificateForThePastYear = [];
	form.declarationOfMajorIllegalRecords = [];
	form.representativeProjects = [];
	form.actualImplementationSituation = [];
	form.other = [];
	testDatas.value = [];
};
// 添加一行
const addRow = (whatAdd: number) => {
	if (whatAdd == 0) {
		let obj: any = {};
		if (testDatas.value.length == 0) {
			obj.index = "0";
			columnList.value.forEach((p: any) => {
				obj[p.prop] = "";
			});
			testDatas.value[0] = obj;
		} else {
			const weiyi = testDatas.value[testDatas.value.length - 1].index;
			columnList.value.forEach((p: any) => {
				obj[p.prop] = "";
			});
			obj.index = String(Number(weiyi) + 1);
			testDatas.value[testDatas.value.length] = obj;
		}
	}
};
//删除
const delRow = (scope: any, whatDel: number) => {
	const arrIndex = scope.$index; //唯一标识
	//将testDatas中的第arrIndex项数据删除
	if (whatDel == 0) {
		testDatas.value.splice(arrIndex, 1);
	}
};
const acceptParams = () => {
	drawerVisible.value = true;
};
defineExpose({
	acceptParams
});
</script>

<style scoped lang="scss">
:deep(.el-textarea__inner) {
	height: 200px;
}
:deep(.cell) {
	text-align: center !important;
	height: 45px;
	padding: 0;
}
.p1111 {
	height: 50px;
	line-height: 50px !important;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	padding: 0;
	margin: 0;
	text-align: center !important;
}
.tableForm {
	width: 700px;
	margin-left: 35px;
	margin-top: 20px;
}
.sepcial_about {
	width: 500px;
	padding-left: 40px;
	box-sizing: border-box;
	margin-bottom: 60px;
	position: relative;

	> :first-child {
		width: 1000px;
		margin-bottom: 10px;
	}
}
.sepcial_about .mt-4 {
	position: absolute;
	width: 40px !important;
	height: 30px !important;
	bottom: 10px;
	left: 800px;
	z-index: 999;
}
.sepcial_about :deep(.el-table) {
	display: block;
	height: 100%;
}
:deep(.el-date-editor) {
	width: 100% !important;
	height: 50px;
	text-align: center;
}
.form-left {
	padding-top: 20px;
}
:deep(.el-form-item__content) {
	/* margin-top: 20px; */
	margin-left: 40px !important;
}
:deep(.el-form-item__label) {
	font-size: 16px;
	color: black;
}
</style>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

缓存雪崩、击穿、穿透及解决方案_保证缓存和数据库一致性

文章目录 缓存雪崩、击穿、穿透1.缓存雪崩造成缓存雪崩解决缓存雪崩 2. 缓存击穿造成缓存击穿解决缓存击穿 3.缓存穿透造成缓存穿透解决缓存穿透 更新数据时&#xff0c;如何保证数据库和缓存的一致性&#xff1f;1. 先更新数据库&#xff1f;先更新缓存&#xff1f;解决方案 2…

C语言函数练习(超基础超详细)

ps:题目来源于pta平台。 1. int sum(int m, int n) {int sum0;for(int im; i<n; i){sumi;}return sum; } 2. int max(int a, int b) {if(a>b)return a;else return b; } 3. double dist( double x1, double y1, double x2, double y2 ) {return sqrt((x1-x2)*(x1…

【Flink】Standalone运行模式

独立模式是独立运行的&#xff0c;不依赖任何外部的资源管理平台&#xff1b;当然独立也是有代价的&#xff1a;如果资源不足&#xff0c;或者出现故障&#xff0c;没有自动扩展或重分配资源的保证&#xff0c;必须手动处理。所以独立模式一般只用在开发测试或作业非常少的场景…

Docker+ Jenkins+Maven+git自动化部署

环境&#xff1a;Centos7 JDK1.8 Maven3.3.9 Git 2.40 Docker 20.10.17 准备工作&#xff1a; 安装Docker Centos7默认的yum安装的docker是1.13&#xff0c;版本太低&#xff0c;很多镜像都要Docker版本要求&#xff0c;升级Docker版本。 卸载已安装Docker: yum …

NeurIPS 2023 | RGIB:对抗双边图噪声的鲁棒图学习

▐ 摘要 链接预测[1,2]是图学习的一种基础任务&#xff0c;用于判断图中的两个节点是否可能相连&#xff0c;被广泛应用于药物发现、知识图谱补全和在线问答等实际场景。尽管图神经网络&#xff08;Graph Neural Network&#xff0c;GNN&#xff09;在该问题的性能上取得了显著…

我做了一个世界杯数据可视化网站······

感兴趣的小伙伴可以进去看看&#xff1a;主页https://messimeimei.github.io/world-cup-visualization.github.io/&#xff0c;可能会比较卡 经过2个月的工作&#xff0c;我完成了80%的工作量&#xff0c;并成功将静态网站进行了部署。并对页面进行了更新。不过当前虽然完成了…

ESP32之避障

ESP32之避障 图片 程序 int Led27;//定义LED 接口 int buttonpin4; //定义光遮断传感器接口 int val;//定义数字变量val void setup() { pinMode(Led,OUTPUT);//定义LED 为输出接口 pinMode(buttonpin,INPUT);//定义避障传感器为输出接口 } void loop() {Serial.begin(9600);…

性能相关的闪存特性

一、多Plane操作 上章提到若干个Plane组成Die或者叫LUN,即一个Die上有多个Plane 每次进行写操作时&#xff0c;控制器先将数据写入页缓存中&#xff0c;等同一个Die上另一个Plane也写数据的时候&#xff0c;再同时写入&#xff0c;原来单独操作一个Plane的时间变成了可以同时做…

UDP客户端使用connect与UDP服务器使用send函数和recv函数收发数据

服务器代码编译运行 服务器udpconnectToServer.c的代码如下&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include<errno.h> #inclu…

【Spring进阶系列丨第四篇】学习Spring中的Bean管理(基于xml配置)

前言 在之前的学习中我们知道&#xff0c;容器是一个空间的概念&#xff0c;一般理解为可盛放物体的地方。在Spring容器通常理解为BeanFactory或者ApplicationContext。我们知道spring的IOC容器能够帮我们创建对象&#xff0c;对象交给spring管理之后我们就不用手动去new对象。…

操作系统发展过程--单道批处理系统、多道批处理系统、分时系统、实时系统

一、单道批处理系统 计算机早期&#xff0c;为了能提高利用率&#xff0c;需要尽量保持系统的连续运行&#xff0c;即在处理完一个作业之后&#xff0c;紧接着处理下一个作业&#xff0c;以减少机器的空闲等待时间 1.单道批处理系统的处理过程 为了实现对作业的连续处理&…

EPT-Net:用于3D医学图像分割的边缘感知转换器

EPT-Net: Edge Perception Transformer for 3D Medical Image Segmentation EPT-Net&#xff1a;用于3D医学图像分割的边缘感知转换器背景贡献实验方法Dual Positional Transformer&#xff08;双位置Transformer&#xff09;Learnable Patch EmbeddingVoxel Spacial Positiona…

OpenCV实现图像噪声、去噪基本方法

一、噪声分类 1、高斯噪声 指服从高斯分布&#xff08;正态分布&#xff09;的一类噪声&#xff0c;其产生的主要原因是由于相机在拍摄时视场较暗且亮度不均匀造成的&#xff0c;同时相机长时间工作使得温度过高也会引起高斯噪声&#xff0c;另外电路元器件白身噪声和互相影响…

土地利用数据技术服务

一、背景介绍 土地是人类赖以生存与发展的重要资源和物质保障&#xff0c;在“人口&#xff0d;资源&#xff0d;环境&#xff0d;发展&#xff08;PRED&#xff09;”复合系统 中&#xff0c;土地资源处于基础地位。随着现代社会人口的不断增长以及工业化、城市化进程的加速&a…

nvm切换版本之后npm用不了

原因是 nvm只给你安了对应的node没给你安装对应的node版本的npm 解决办法如下 1找到你安装的node版本号 然后去官网下载对应的版本包 这个网址就是node官网的版本列表 Index of /download/release/ 2下载后解压 把根目录这俩复制到自己的nvm安装目录下 还有那个node_modul…

Vue学习之路------指令

Vue指令 vue会根据不同的指令&#xff0c;针对标签实现不同的功能 指令:带有v-前缀的特殊标签属性 1&#xff1a;v-html&#xff1a;指令 <div v-html"msg"></div> 2&#xff1a;v-show 作用&#xff1a;控制元素显示隐藏 语法&#xff1a;v-show&quo…

解决:javax.websocket.server.ServerContainer not available 报错问题

原因&#xff1a; 用于扫描带有 ServerEndpoint 的注解成为 websocket&#xff0c;该方法是 服务器端点出口&#xff0c;当进行 SpringBoot 单元测试时&#xff0c;并没有启动服务器&#xff0c;所以当加载到这个bean时会报错。 解决方法&#xff1a; 加上这个注解内容 Spr…

顺序表基本操作全面解析

文章目录 1.线性表2.顺序表分类2.1 静态顺序表2.2 动态顺序表 3. 顺序表各接口实现1. 定义结构体(Seqlist)2. 结构体初始化(SLInit)3.检查容量 (SLCheckCapacity)4.打印数据 (SLPrintf)5.插入操作5.1 从数据头部插入(SLPushFront)5.2 从数据尾部插入(SLPushBack)5.3 从任意下标…

ELK企业级日志分析平台——kibana数据可视化

部署 新建虚拟机server5&#xff0c;部署kibana [rootelk5 ~]# rpm -ivh kibana-7.6.1-x86_64.rpm [rootelk5 ~]# cd /etc/kibana/[rootelk5 kibana]# vim kibana.ymlserver.host: "0.0.0.0"elasticsearch.hosts: ["http://192.168.56.11:9200"]i18n.local…

项目管理套路:看这一篇绝对够用❤️

写论文必不可少的&#xff0c;就是创建代码并进行实验。好的项目管理可以让实验进行得更加顺利。本篇博客以一次项目实践为例&#xff0c;介绍项目管理的方法&#xff0c;以及可能遇到的问题&#xff0c;并提供一些可行的解决方案。 目录 项目管理工具开始第一步版本管理十分关…