vue调用Element-ui 表格实现动态添加删除行数据及视图切换
一、 预期效果如下
-
当不需要编辑时
此时,表单部分网络结构名为下拉框,发布和图像类型为不可选择状态,其他输入框为只读状态;表格部分为正常的视图,不可编辑。
当对结构名进行选择后,表单和表格内容会进行初始化。
-
当需要进行编辑时
这里以修改为例(新建雷同,区别为新建时表格和表单内容会清空)。
此时,表单部分:结构名由下拉框变为输入框,其他输入框由可读变为可编辑,类型也可以进行选择;表格部分新增添加和清空及操作栏按键,同时底部按键发生了部分变化,确定按键消失,复制、修改、新建、上传按键为不可点击状态(可视清空隐藏也可),同时新增了保存和取消按键,取消会将新建和修改后的数据清空,恢复最初的数据。
二、代码如下
部分需要调用后端接口的代码不进行展示了,按需添加
<template>
<!-- 卷积神经网络结构-->
<div>
<el-dialog v-bind="$attrs"
v-on="$listeners"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="show"
width="50vw"
align="center"
:title="title">
<!-- 表单 -->
<el-row :gutter="10">
<el-form ref="elForm" :model="formData" :rules="rules" size="small" label-width="100px">
<el-col :span="24">
<el-form-item label-width="120px" label="网络结构名" prop="netStructureName">
<!-- 视图模式 -->
<el-select v-model="formData.netId" placeholder="请选择网络结构名" clearable
:style="{width: '100%'}"
@change="initTableAndForm"
v-if="state === 'view'">
<el-option v-for="(item, index) in netStructureNameOptions" :key="index" :label="item.netStructureName"
:value="item.netId" :disabled="item.disabled"></el-option>
</el-select>
<!-- 编辑模式 -->
<el-input v-model="formData.netStructureName" placeholder="请输入网络结构名" clearable
:style="{width: '100%'}"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label-width="120px" label="来源发布者" prop="netPublisher">
<el-input v-model="formData.netPublisher" placeholder="请输入来源发布者" clearable
:style="{width: '100%'}"
:readonly="state === 'view'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label-width="120px" label="发布类型" prop="netPublishedType">
<el-select v-model="formData.netPublishedType" placeholder="请输入网络结构名" clearable
:style="{width: '100%'}"
:disabled="state === 'view'">
<el-option v-for="(item, index) in netPublishedTypeOptions" :key="index" :label="item.label"
:value="item.value" :disabled="item.disabled"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label-width="120px" label="处理图像大小" prop="imgSize">
<el-input v-model="formData.imgSize" placeholder="请输入处理图像大小" clearable
:style="{width: '100%'}"
:readonly="state === 'view'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label-width="120px" label="图像类型" prop="imgStyle">
<el-select v-model="formData.imgStyle" placeholder="请输入图像类型" clearable
:style="{width: '100%'}" :disabled="state === 'view'">
<el-option v-for="(item, index) in imgStyleOptions" :key="index" :label="item.label"
:value="item.value" :readonly="item.disabled"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="memo">
<el-input v-model="formData.memo" type="textarea" placeholder="请输入备注" :maxlength="100"
show-word-limit :autosize="{minRows: 3, maxRows: 4}"
:style="{width: '100%'}"
:readonly="state === 'view'"></el-input>
</el-form-item>
</el-col>
<el-col :span="24" v-if="state === 'edit' || state === 'add' || state === 'uploadV'"
style="display: flex;justify-content: flex-end;">
<el-button type="primary" size="small" @click="addRow" icon="el-icon-plus">
添加
</el-button>
<el-button type="primary" size="small" @click="clearAll" icon="el-icon-delete">
清空
</el-button>
</el-col>
</el-form>
</el-row>
<br>
<!-- 表格 -->
<el-table
:data="tableData"
size="mini"
height="200px"
border>
<el-table-column
type="index"
align="center"
label="序号"
:index="indexMethod">
</el-table-column>
<el-table-column
align="center"
prop="layerStyle"
label="层类型">
<template v-slot="scope">
<el-select v-model="scope.row.layerStyle" clearable placeholder="请输入层类型" size="mini"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'">
<el-option
v-for="item in layerStyleOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<span v-if="state === 'view'">{{ scope.row.layerStyle }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
prop="kernelSize"
label="卷积核大小">
<template v-slot="scope">
<el-input placeholder="请输入卷积核大小"
size="mini"
v-model="scope.row.kernelSize"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'"></el-input>
<span v-if="state === 'view'">{{ scope.row.kernelSize }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
prop="kernelCount"
label="卷积核数量">
<template v-slot="scope">
<el-input placeholder="请输入卷积核数量"
size="mini"
v-model="scope.row.kernelCount"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'"></el-input>
<span v-if="state === 'view'">{{ scope.row.kernelCount }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
prop="stepSize"
label="步长">
<template v-slot="scope">
<el-input placeholder="请输入步长"
size="mini"
v-model="scope.row.stepSize"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'"></el-input>
<span v-if="state === 'view'">{{ scope.row.stepSize }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
label="操作"
width="120"
v-if="state === 'edit' || state === 'add' || state === 'uploadV'">
<template slot-scope="scope">
<el-button type="text" size="small"
@click.native.prevent="addRow">新增
</el-button>
<el-button type="text" size="small"
@click.native.prevent="deleteRow(scope.$index, tableData)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer" align="center" style="margin-top: -3%">
<el-button type="primary" size="small" @click="cloneShow"
:disabled="state === 'edit' || state === 'add' || state === 'copy' || state === 'uploadV'">复制
</el-button>
<el-button type="primary" size="small" @click="edit"
:disabled="state === 'edit' || state === 'add' || state === 'copy' || state === 'uploadV'">修改
</el-button>
<el-button type="primary" size="small" @click="add"
:disabled="state === 'edit' || state === 'add' || state === 'copy' || state === 'uploadV'">新建
</el-button>
<el-button type="primary" size="small"
v-show="state === 'view'"
@click="selectData">确定
</el-button>
<el-button type="primary" size="small"
v-show="state === 'edit' || state === 'add'"
@click="handleConfirm">保存
</el-button>
<el-button type="primary" size="small"
@click="uoloadSave"
v-show="state === 'uploadV'">保存
</el-button>
<el-button type="primary" size="small"
v-show="state === 'edit' || state === 'add' || state === 'copy' || state === 'uploadV'"
@click="handleCancel">取消
</el-button>
</div>
</el-dialog>
<el-dialog
title="复制重命名"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="dialogVisible">
<el-form ref="form" :model="copyFormDataV1" label-width="120px" :rules="rulesV1">
<el-form-item label="网络结构名" prop="newNetStructureName">
<el-input v-model="copyFormDataV1.newNetStructureName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="clone">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "networkStructure",
// 避免父作用域的不被认作props的特性绑定应用在子组件的根元素上
inheritAttrs: false,
components: {},
props: {},
data() {
return {
fullscreenLoading: false,// 加载动画
// 复制配置框
dialogVisible: false,
// 视图模式:查看view,新建add,编辑:edit,复制copy,上传:upload
state: 'view',
show: false,
title:'默认',
formData: {
netId: undefined,
netStructureName: undefined,
netPublisher: undefined,
netPublishedType: undefined,
imgSize: undefined,
imgStyle: undefined,
cNNUpLoad: undefined,
memo: undefined,
aNodeCnnNetList: []
},
copyFormData: {
aNodeCnnNetList: []
},// 表单数据拷贝
copyFormDataV1: {
newNetStructureName: undefined
},// 表单数据拷贝
tableData: [/*{
layerNo: 1,
layerStyle: '卷积层',
kernelSize: 3,
kernelCount: 20,
stepSize: 20,
}*/],
copyTableData: [],// 表格数据拷贝
multipleSelection: [],
rules: {
netStructureName: [{
required: true,
message: '请输入网络结构名',
trigger: 'blur'
}],
netPublisher: [{
required: true,
message: '请输入来源发布者',
trigger: 'blur'
}],
netPublishedType: [{
required: true,
message: '发布类型不能为空',
trigger: 'change'
}],
imgSize: [{
required: true,
message: '请输入处理图像大小',
trigger: 'blur'
}],
imgStyle: [{
required: true,
message: '请输入图像类型',
trigger: 'change'
}],
cNNUpLoad: [],
memo: [],
},
// 复制弹窗重名名,非空验证
rulesV1: {
newNetStructureName: [{
required: true,
message: '请输入网络结构名',
trigger: 'blur'
}]
},
// 网络结构名,调用后端接口进行初始化
netStructureNameOptions: [],
// 卷积层类型
layerStyleOptions: [{
"label": "卷积层",
"value": "卷积层"
}, {
"label": "池化层",
"value": "池化层"
}, {
"label": "展平层",
"value": "展平层"
}, {
"label": "全连接层",
"value": "全连接层"
}, {
"label": "dropout",
"value": "dropout"
}],
// 发布类型
netPublishedTypeOptions: [{
"label": "自定义",
"value": "自定义"
}, {
"label": "外部共享",
"value": "外部共享"
}],
// 图像类型
imgStyleOptions: [{
"label": "黑白",
"value": 1
}, {
"label": "彩色",
"value": 3
}],
}
},
computed: {},
watch: {
// 监听弹窗状态,当弹窗关闭可以进行部分数据的初始化
show(val) {
if (!val) {
this.copyFormData = {
aNodeCnnNetList: []
};
this.copyTableData = [];
this.reset()
//视图切换
this.state = "view";
}
}
},
created() {
this.getNetStructureList()
},
mounted() {
},
methods: {
//获取全部网络结构名称,初始化下拉框
getNetStructureList() {
//调用后端接口
},
//下拉框选择,初始化表单和表格数据
initTableAndForm(data) {
// eslint-disable-next-line no-console
console.log(data);
},
// 卷积网络架构修改
edit() {
if (this.formData.netStructureName != undefined) {
// 数据克隆,方便取消还原数据
this.copyFormData = JSON.parse(JSON.stringify(this.formData))
this.copyTableData = JSON.parse(JSON.stringify(this.tableData))
//视图切换
this.state = 'edit'
} else {
this.$message.warning({
title: '警告',
message: "请先对网络结构名进行选择~",
duration: 2000
})
}
},
// 克隆重命名弹窗展示
cloneShow() {
if (this.formData.netStructureName != undefined) {
this.dialogVisible = true
} else {
this.$message.warning({
title: '警告',
message: "请先对网络结构名进行选择~",
duration: 2000
})
}
},
// 复制卷积网络结构
clone() {
// 数据克隆及复制,表格对象封装到表格对象中
if (this.formData != undefined) {
this.copyFormData = JSON.parse(JSON.stringify(this.formData))
this.copyFormData.netStructureName = this.copyFormDataV1.newNetStructureName
}
if (this.tableData != undefined) {
this.copyTableData = JSON.parse(JSON.stringify(this.tableData))
this.copyFormData.aNodeCnnNetList = this.copyTableData
}
//视图切换
this.state = 'copy'
// eslint-disable-next-line no-console
},
// 确定选择该架构
selectData() {
if (this.formData.netStructureName != undefined) {
this.$emit("networkStructure", this.formData)
this.show = false
} else {
this.$message.warning({
title: '警告',
message: "请先对网络结构名进行选择~",
duration: 2000
})
}
},
// 新建卷积网络结构
//新建的时候先拷贝,再进行表单,表格重置
add() {
if (this.formData != undefined) {
this.copyFormData = JSON.parse(JSON.stringify(this.formData))
}
if (this.tableData != undefined) {
this.copyTableData = JSON.parse(JSON.stringify(this.tableData))
}
// this.$refs['elForm'].resetFields() 初始化表单,非清空
this.reset()
// 视图切换
this.state = 'add'
},
// 保存修改,新建的内容
handleConfirm() {
this.$refs['elForm'].validate(valid => {
if (valid) {
// eslint-disable-next-line no-console
console.log(valid)
}
})
},
// 取消新建,修改状态,并还原数据
handleCancel() {
this.tableData = JSON.parse(JSON.stringify(this.copyTableData))
this.formData = JSON.parse(JSON.stringify(this.copyFormData))
//视图切换
this.state = 'view'
},
// 表格删除行数据
deleteRow(index, rows) {
rows.splice(index, 1);
},
// 表格新增行数据
addRow() {
if (this.tableData == undefined) {
this.tableData = new Array();
}
let obj = {};
this.tableData.push(obj);
},
// 表格清空所有行
clearAll() {
this.tableData = undefined
},
// 表格自定义序列号
indexMethod(index) {
return index + 1;
},
//表单,表格重置
reset() {
this.formData = {
netStructureName: undefined,
netPublisher: undefined,
netPublishedType: undefined,
imgSize: undefined,
imgStyle: undefined,
cNNUpLoad: undefined,
memo: undefined,
aNodeCnnNetList: []
},
this.tableData = undefined
}
}
}
</script>
<style>
</style>