vue3使用AntDesign<a-table>左右拖拽列及下拉框新增自定义数据

1、左右拖拽列

安装依赖

pnpm install sortablejs

引入

import Sortable from 'sortablejs';
 onMounted(() => {
  const container = document.querySelector('.ant-table-thead > tr');
  new Sortable(container, {
    filter: '.ant-table-selection-column, .ant-table-cell-fix-right-first', // 忽略选择列和操作列
    handle: '.ant-table-cell',
    animation: 150,
    onStart:(evt) => {
      console.log('开始拖拽的时候')
    },
    onEnd: (evt) => {
      const { oldIndex, newIndex } = evt;
      if (oldIndex !== newIndex) {
        const movedItem = columns.value.splice(oldIndex-1, 1)[0]; // 这里减1是列表有选择框
        columns.value.splice(newIndex-1, 0, movedItem);
        localStorage.setItem('computedColumns', JSON.stringify(columns.value));
      }
    }
  });
});

以上基本上就能实现左右拖拽了,但是会有的问题,目前空置的是选择列和操作列是不能拖动的,但是倒数第二列如果要拖到最后一列还是可以拖动的,目前没有找到解决方法,如果有解决的欢迎评论区代码附上一起探讨
2、下拉框新增自定义数据
在这里插入图片描述

<a-select
	allowClear
	@dropdownVisibleChange="changeMointor"
	placeholder="请选择入监控节点"
	ref="select"
	style="width: 180px"
	v-model:value="addexcludepool.intranetInControl"
	:options="hostIPData"
	:getPopupContainer="(triggerNode) => triggerNode.parentNode"
>
	<template #dropdownRender="{ menuNode: menu }">
		<v-nodes :vnodes="menu" />
		<a-divider style="margin: 4px 0" />
		<div style="padding: 4px 8px; cursor: pointer;color:#1677FF" @mousedown.prevent="handleAddClick">
			<plus-outlined />
			新增入监控节点
		</div>
	</template>	
</a-select>
const  VNodes = ref((_, {
  attrs,
}) => {
  return attrs.vnodes;
})
const handleAddClick = () => {
	console.log('逻辑内容)
}
<think>好的,我需要帮用户解决如何将给定的JSON表单数据结构渲染到Vue页面上,并实现新增、删除、修改表单字段的功能。首先,我得分析用户提供的JSON结构,看看每个字段的类型和要求。 用户提供的JSON数组里有四个元素,每个都有type、label、model、rules等属性。其中el-input和el-select是Element UI的组件,所以需要确认用户是否使用Element UI。根据常见的实践,可能用户正在使用Vue 2和Element UI,因此我需要基于这个假设来构建代码。 接下来,我需要考虑如何动态渲染这些表单字段。Vue的动态组件可能有用,比如用component :is来根据类型渲染不同的组件。同时,对于el-select,需要处理options数据,可能需要将options传递到组件中。 然后,表单验证是通过rules属性定义的,需要确保每个字段的验证规则正确应用到对应的表单组件上。Element UI的el-form-item的prop属性需要和model中的字段对应,这里可能需要使用嵌套对象,比如表单数据模型设计为formData[field.model],然后prop设置为对应的路径。 新增、删除、修改字段的功能需要用户能够编辑JSON结构,可能需要一个编辑界面,允许用户添加新的字段配置,或者修改现有的配置。这部分可能需要一个模态框或可编辑的表格,让用户调整每个字段的属性,比如label、type、options等。 数据存储方面,用户提到数据库,但前端的实现主要是操作JSON数据,所以可能需要将修改后的JSON保存到后端,这里可能需要调用API,但用户主要关注前端实现,所以重点放在前端的状态管理。 具体步骤可能包括: 1. 使用el-form渲染动态表单,根据JSON配置生成对应的el-input或el-select组件。 2. 表单的数据模型需要动态绑定,可能使用一个对象,键是各字段的model值。 3. 验证规则需要动态应用到每个表单项,可能需要将rules属性传递给el-form-item。 4. 实现一个管理界面,展示当前字段配置,允许用户添加、删除、编辑每个字段的配置。 5. 在管理界面中,对于el-select类型,需要能够编辑options数组,比如添加或删除选项。 6. 数据持久化方面,可能需要将最终的JSON结构保存到后端数据库,但前端部分主要是处理状态的变化和提交。 可能的代码结构: - 主组件包含动态表单和管理按钮。 - 使用v-for遍历fields数组,生成对应的表单组件。 - 对于el-select,需要嵌套options的循环生成el-option。 - 管理界面可能是一个对话框,里面有一个可编辑的表,每个字段可以编辑其属性。 - 新增字段时,添加一个新的配置对象到fields数组中。 - 删除字段时,从数组中移除对应的项。 - 修改字段时,更新数组中的对应对象。 需要注意的点: - 动态组件的正确渲染,特别是el-input和el-select的不同处理。 - 表单验证的动态绑定,确保rules正确应用。 - 管理界面中的表单配置编辑,需要处理不同类型的字段属性,如options只在el-select中存在。 - 数据绑定的正确性,尤其是在嵌套对象或数组时,Vue的响应式更新可能需要使用Vue.set或展开运算符。 可能的代码示例: 在模板部分,动态渲染表单字段: <el-form :model="formData" :rules="formRules"> <template v-for="(field, index) in fields"> <el-form-item :label="field.label" :prop="field.model" :rules="field.rules"> <component :is="field.type" v-model="formData[field.model]" v-bind="field.attrs" > <el-option v-if="field.type === &#39;el-select&#39;" v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value" /> </component> </el-form-item> </template> </el-form> 管理界面部分,可能需要遍历fields数组,允许编辑每个字段的属性,比如类型、label、options等。新增字段时,push一个新的配置对象到fields数组,删除时使用splice。修改时直接修改数组中的对象属性,由于Vue的响应式系统,视图会自动更新。 此外,需要处理表单验证规则的转换,因为原始JSON中的rules可能包含required等属性,需要确保它们符合Element UI的规则格式。 可能遇到的坑: - 动态绑定prop时,如果model是嵌套对象,可能需要使用如&#39;formData.&#39; + field.model,但用户提供的例子中model是直接字符串,如"电压",所以formData应该是平铺结构。 - 动态组件的v-model绑定,需要正确指向formData中的属性。 - 在管理界面中编辑字段配置时,需要深度复制原始数据,避免直接修改导致视图不必要的更新。 综上所述,需要编写动态渲染表单的代码,处理不同组件类型的逻辑,以及实现字段配置的管理功能,包括增删改。同时确保表单验证和数据的正确绑定。</think>以下是如何实现动态表单渲染和字段管理的详细解决方案,基于Vue 2 + Element UI技术栈: ```html <template> <!-- 动态表单展示区域 --> <div class="form-container"> <el-form :model="formData" :rules="formRules" ref="dynamicForm" label-width="100px" > <template v-for="(field, index) in fields"> <el-form-item :key="index" :label="field.label" :prop="field.model" :rules="field.rules" > <!-- 动态组件渲染 --> <component :is="field.type" v-model="formData[field.model]" v-bind="field.attrs" > <!-- 处理select选项 --> <el-option v-if="field.type === &#39;el-select&#39;" v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value" /> </component> </el-form-item> </template> </el-form> <!-- 字段管理区域 --> <div class="management"> <el-button @click="openFieldEditor(-1)">新增字段</el-button> <el-table :data="fields"> <el-table-column prop="label" label="字段名称"></el-table-column> <el-table-column label="操作"> <template #default="{ $index }"> <el-button size="mini" @click="openFieldEditor($index)">编辑</el-button> <el-button size="mini" type="danger" @click="deleteField($index)">删除</el-button> </template> </el-table-column> </el-table> </div> <!-- 字段编辑对话框 --> <el-dialog :title="isEdit ? &#39;编辑字段&#39; : &#39;新增字段&#39;" :visible.sync="dialogVisible" > <field-editor :current-field="currentField" @confirm="handleFieldConfirm" /> </el-dialog> </div> </template> <script> // 独立字段编辑器组件 const FieldEditor = { props: [&#39;currentField&#39;], data() { return { localField: this.currentField ? { ...this.currentField } : { type: &#39;el-input&#39;, label: &#39;&#39;, model: &#39;&#39;, rules: {}, attrs: {}, options: [] } } }, methods: { addOption() { this.localField.options.push({ label: &#39;&#39;, value: &#39;&#39; }) }, removeOption(index) { this.localField.options.splice(index, 1) } }, template: ` <div> <el-form label-width="80px"> <el-form-item label="字段类型"> <el-select v-model="localField.type"> <el-option label="输入框" value="el-input" /> <el-option label="下拉框" value="el-select" /> </el-select> </el-form-item> <el-form-item label="字段标签"> <el-input v-model="localField.label" /> </el-form-item> <el-form-item label="字段标识"> <el-input v-model="localField.model" /> </el-form-item> <template v-if="localField.type === &#39;el-select&#39;"> <el-form-item label="选项配置"> <div v-for="(opt, idx) in localField.options" :key="idx"> <el-input v-model="opt.label" placeholder="显示文本" style="width: 45%; margin-right: 5%" /> <el-input v-model="opt.value" placeholder="实际值" style="width: 45%" /> <el-button @click="removeOption(idx)">删除</el-button> </div> <el-button @click="addOption">添加选项</el-button> </el-form-item> </template> </el-form> </div> ` } export default { components: { FieldEditor }, data() { return { fields: [...], // 初始数据使用你提供的JSON formData: {}, formRules: {}, dialogVisible: false, currentIndex: -1, currentField: null } }, watch: { fields: { deep: true, handler(newVal) { // 动态生成验证规则 this.formRules = newVal.reduce((rules, field) => { rules[field.model] = field.rules return rules }, {}) // 初始化表单数据 this.formData = newVal.reduce((data, field) => { data[field.model] = &#39;&#39; return data }, {}) }, immediate: true } }, methods: { openFieldEditor(index) { this.currentIndex = index this.currentField = index >= 0 ? { ...this.fields[index] } : null this.dialogVisible = true }, deleteField(index) { this.fields.splice(index, 1) }, handleFieldConfirm(newField) { if (this.currentIndex >= 0) { this.fields.splice(this.currentIndex, 1, newField) } else { this.fields.push(newField) } this.dialogVisible = false } } } </script> ``` 关键实现要点说明: 1. **动态表单渲染**: - 使用`component`动态组件实现不同类型控件的渲染 - 通过`v-for`遍历字段配置数据生成表单项 - 自动处理下拉框的`el-option`选项配置 2. **数据管理**: - 使用`formData`对象存储表单值,通过`model`字段动态绑定 - 自动生成Element UI需要的验证规则格式 - 使用watch监控字段配置变化,自动更新表单数据 3. **字段管理功能**: - 表格展示当前所有字段配置 - 提供新增、编辑、删除操作入口 - 使用独立组件`FieldEditor`处理字段配置编辑 - 支持下拉框选项的动态增减 4. **校验规则处理**: - 自动将字段配置中的`rules`转换为Element UI需要的格式 - 保持与Element UI表单验证的兼容性 5. **数据持久化**: - 实际使用时需要将`this.fields`提交到后端保存 - 初始化时从后端获取字段配置数据 扩展建议: 1. 添加字段类型验证(如model值唯一性校验) 2. 增加字段排序功能(拖拽排序) 3. 添加字段配置的本地缓存 4. 完善表单验证的提示信息 5. 增加字段默认值配置项 使用时需要确保: 1. 已正确安装Element UI 2. 所有`model`值保持唯一性 3. 下拉框字段必须包含`options`配置 4. 表单提交时调用`this.$refs.dynamicForm.validate()`进行验证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张张Z7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值