返回

Form.List 案例详解,教你玩转复杂表单

前端

在最近研发的项目中,小编遇到一个比(you)较(dian)复(bian)杂(tai)的表单需求。讲真不难,就是构造数据和数据处理有点麻烦。起初画好页面后,以为万事大吉,直接掉接口塞数据就成。直到看到后台返回的数据结构,我才意识到自己想得太简单了。

后台返回的数据结构はこんな感じ:

{
  "form": {
    "name": "复杂表单",
    "fields": [
      {
        "name": "姓名",
        "type": "text",
        "required": true
      },
      {
        "name": "年龄",
        "type": "number",
        "required": true
      },
      {
        "name": "性别",
        "type": "radio",
        "options": [
          {
            "value": "男",
            "label": "男"
          },
          {
            "value": "女",
            "label": "女"
          }
        ],
        "required": true
      },
      {
        "name": "爱好",
        "type": "checkbox",
        "options": [
          {
            "value": "篮球",
            "label": "篮球"
          },
          {
            "value": "足球",
            "label": "足球"
          },
          {
            "value": "羽毛球",
            "label": "羽毛球"
          }
        ],
        "required": false
      },
      {
        "name": "备注",
        "type": "textarea",
        "required": false
      }
    ]
  }
}

看到这个数据结构,我瞬间懵逼了。这哪里是表单数据,分明就是一棵树啊!而且这棵树的结构还相当复杂,有根节点、有子节点、还有叶子节点。

不过,既然后台已经把数据结构设计成这样了,我们也只能硬着头皮上了。

首先,我们需要把这个数据结构转换成前端能识别的格式。我们使用 Vue.js 框架,所以需要把数据转换成 Vuex 的 store 格式。

const store = new Vuex.Store({
  state: {
    form: {
      name: "",
      age: "",
      gender: "",
      hobbies: [],
      remark: ""
    }
  },
  mutations: {
    updateForm(state, payload) {
      state.form = payload;
    }
  }
});

然后,我们需要编写一个组件来渲染表单。这个组件需要根据数据结构动态生成表单字段。

<template>
  <div>
    <form>
      <div v-for="field in form.fields" :key="field.name">
        <label>{{ field.name }}</label>
        <input v-if="field.type === 'text'" type="text" v-model="form[field.name]">
        <input v-if="field.type === 'number'" type="number" v-model="form[field.name]">
        <radio-group v-if="field.type === 'radio'" :options="field.options" v-model="form[field.name]"></radio-group>
        <checkbox-group v-if="field.type === 'checkbox'" :options="field.options" v-model="form[field.name]"></checkbox-group>
        <textarea v-if="field.type === 'textarea'" v-model="form[field.name]"></textarea>
      </div>
      <button type="submit">提交</button>
    </form>
  </div>
</template>

<script>
import RadioGroup from "@/components/RadioGroup.vue";
import CheckboxGroup from "@/components/CheckboxGroup.vue";

export default {
  components: {
    RadioGroup,
    CheckboxGroup
  },
  data() {
    return {
      form: this.$store.state.form
    };
  },
  methods: {
    submitForm() {
      this.$store.commit("updateForm", this.form);
      // 将表单数据提交给后台
    }
  }
};
</script>

最后,我们需要编写一个路由来处理表单提交请求。

const router = new VueRouter({
  routes: [
    {
      path: "/form",
      component: Form
    }
  ]
});

到这里,一个完整的复杂表单就开发完成了。是不是很简单?

当然,这只是一个小例子。在实际项目中,你可能会遇到更加复杂的情况。但只要你掌握了基本原理,相信你一定能轻松应对。

希望这篇文章对你有帮助。如果你有任何问题,欢迎随时留言。