You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 动态生成表单元素时数据绑定与值存储的实现方案

问题原因
  • v-model语法错误:模板中给v-model加了:前缀(即:v-model),这会被解析为动态绑定v-model属性,而非启用Vue的双向绑定语法,输入内容完全不会同步到关联变量。
  • contentArray初始化不灵活:当前写死了长度为9的初始数组,若传入的content配置项数量超过9,后续的表单项会绑定到不存在的数组下标,也会出现绑定失效。
  • v-for的key值不规范:直接用item对象作为key,若存在重复配置项会导致渲染异常,建议用配置项的唯一标识或者下标作为key。
修复方案

第一步:修正模板语法

删除所有v-model前的冒号,调整v-for的key:

<div v-for="(item, index) in content" :key="index">
  <template v-if="item.type == 'inputField'" style="margin-top: 1rem;">
    <label>{{ item.label }}</label>
    <input
      type="text"
      v-model="contentArray[index]"
      placeholder="Enter text"
    />
  </template>

  <template v-if="item.type == 'textArea'" style="margin-top: 1rem;">
    <label>{{ item.label }}</label>
    <textarea
      name="textarea"
      v-model="contentArray[index]"
      cols="10"
      rows="10"
    ></textarea>
  </template>
</div>
<button label="submit" @click="getAllData" />

第二步:修正setup逻辑

根据传入的配置动态初始化contentArray,无需写死长度:

setup(props) {
  const displayDialog = ref(false);
  // 按传入的content长度动态初始化
  const contentArray = ref(props.content.map(() => null));

  const open = () => {
    displayDialog.value = true;
  };
  const close = () => {
    displayDialog.value = false;
    // 可选:关闭弹窗时清空表单内容
    contentArray.value = props.content.map(() => null);
  };

  const getAllData = () => {
    console.log(contentArray.value);
  }

  return {
    displayDialog, open, close, getAllData, contentArray
  }
}
更优实现方案

当前用数组存储表单值,使用时需要手动对应下标和表单项的关系,维护成本高。推荐给每个配置项增加field字段,用对象存储表单值,提交时直接返回键值对,使用更便捷:

调整组件使用方式

<ReusableDialog
  :content="[ 
    {label: '用户名', type: 'inputField', field: 'username'}, 
    {label: '个人简介', type: 'textArea', field: 'bio'} 
  ]"
/>

调整组件逻辑

setup(props) {
  const displayDialog = ref(false);
  // 用reactive对象存储表单键值对
  const formData = reactive(
    props.content.reduce((prev, curr) => {
      prev[curr.field] = null
      return prev
    }, {})
  )

  const open = () => {
    displayDialog.value = true;
  };
  const close = () => {
    displayDialog.value = false;
    Object.keys(formData).forEach(key => formData[key] = null)
  };

  const getAllData = () => {
    // 直接返回键值对结构,无需对应下标
    console.log({...formData})
  }

  return {
    displayDialog, open, close, getAllData, formData
  }
}

调整模板绑定

<input
  type="text"
  v-model="formData[item.field]"
  placeholder="Enter text"
/>
<!-- textarea绑定逻辑同理 -->
<textarea
  v-model="formData[item.field]"
  cols="10"
  rows="10"
></textarea>

内容的提问来源于stack exchange,提问作者Nora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 14:24:02