手记

Form.List 动态表单入门:轻松掌握动态表单构建技巧

概述

本文将详细介绍如何使用 Form.List 创建灵活的动态表单,包括基本配置、添加和删除表单项的方法,以及与验证和外部数据源的集成。通过实际案例,你将学会如何在多地址录入、多联系人录入和问卷调查等场景中应用 Form.List 组件。

引入 Form.List 组件

Form.List 是一个强大的动态表单组件,广泛应用于需要动态添加、删除、修改表单项的场景中。它允许开发者通过简单的配置和编程逻辑来实现灵活的表单构建。以下是 Form.List 组件的基本概述及其使用场景。

什么是 Form.List 组件

Form.List 组件允许你创建可扩展的表单,这些表单会根据数据的动态变化进行相应的更新。它通常用于需要用户输入多个相似但独立的数据集的场景,例如用户可以添加多个地址、多个联系人信息,或者创建一个包含多道题目的问卷。

使用场景

  1. 多地址录入: 用户可以动态添加多个住址。
  2. 多联系人录入: 动态添加多个联系人信息。
  3. 购物车管理: 动态添加、修改购物车中的商品。
  4. 问卷调查: 动态添加多个问题选项。

安装与基础配置

Form.List 组件的使用通常依赖于一个特定的框架或库。以 Ant Design 的 Form.List 为例,首先需要安装相关的依赖。

npm install antd

安装完成后,可以使用以下代码进行基础配置:

import { Form, Input, Button, List } from 'antd';
import React, { useState } from 'react';

const Demo = () => {
  const [form] = Form.useForm();
  const [items, setItems] = useState([{ key: '1' }]);

  return (
    <Form form={form}>
      <Form.List name="items">
        {(fields, { add, remove }) => {
          return (
            <>
              {fields.map((field, index) => (
                <div key={field.key}>
                  <Form.Item {...field} shouldUpdate={(prevValues, currentValues) => prevValues.value !== currentValues.value}>
                    <Input />
                  </Form.Item>
                  {fields.length > 1 ? (
                    <Button type="link" onClick={() => remove(field.name)}>
                      删除
                    </Button>
                  ) : null}
                </div>
              ))}
              <Button type="dashed" onClick={() => add()} block>
                添加新的输入框
              </Button>
            </>
          );
        }}
      </Form.List>
    </Form>
  );
};

export default Demo;

基本用法

创建一个简单的动态表单

在创建动态表单时,首先需要引入 Form.List 组件,并进行基础配置。以下是一个简单的示例,展示如何创建一个可以动态添加或删除表单项的表单。

import React from 'react';
import { Form, Input, Button, List } from 'antd';

const App = () => {
  const [form] = Form.useForm();
  const [items, setItems] = useState([{ key: '1' }]);

  const add = () => {
    setItems([...items, { key: `${items.length + 1}` }]);
  };

  const remove = (key) => {
    const itemsCopy = [...items];
    const index = itemsCopy.findIndex((item) => item.key === key);
    itemsCopy.splice(index, 1);
    setItems(itemsCopy);
  };

  return (
    <Form form={form}>
      <Form.List name="items">
        {(fields, { add, remove }) => {
          return (
            <>
              {fields.map(({ key, name, fieldKey, ...restField }) => (
                <Form.Item
                  key={key}
                  {...restField}
                  shouldUpdate={(prevValues, currentValues) =>
                    prevValues.value !== currentValues.value
                  }
                >
                  <Input />
                </Form.Item>
              ))}
              <Button type="dashed" onClick={add} block>
                添加新的输入框
              </Button>
            </>
          );
        }}
      </Form.List>
    </Form>
  );
};

export default App;

添加和删除表单项

在上一个示例中,我们通过 addremove 方法实现了表单项的添加和删除。具体实现如下:

const add = () => {
  setItems([...items, { key: `${items.length + 1}` }]);
};

const remove = (key) => {
  const itemsCopy = [...items];
  const index = itemsCopy.findIndex((item) => item.key === key);
  itemsCopy.splice(index, 1);
  setItems(itemsCopy);
};

显示和隐藏表单项

可以通过 Form.List 组件的参数控制表单项的显示和隐藏。例如,当表单项的值为空时,可以隐藏该表单项。

<Form.List name="items">
  {(fields, { add, remove }) => {
    return (
      <>
        {fields.map(({ key, name, fieldKey, ...restField }) => (
          <Form.Item
            key={key}
            {...restField}
            shouldUpdate={(prevValues, currentValues) =>
              prevValues.value !== currentValues.value
            }
          >
            {currentValues.value ? (
              <Input />
            ) : null}
          </Form.Item>
        ))}
        <Button type="dashed" onClick={add} block>
          添加新的输入框
        </Button>
      </>
    );
  }}
</Form.List>

动态表单项的处理

如何添加新的表单项

添加新的表单项可以通过 add 方法实现,该方法会生成一个新的表单项并将其添加到表单项数组中。

const add = () => {
  setItems([...items, { key: `${items.length + 1}` }]);
};

如何移除已有的表单项

移除已有的表单项可以通过 remove 方法实现,该方法会通过表单项的唯一标识 key 来找到对应的表单项,并将其从数组中移除。

const remove = (key) => {
  const itemsCopy = [...items];
  const index = itemsCopy.findIndex((item) => item.key === key);
  itemsCopy.splice(index, 1);
  setItems(itemsCopy);
};

如何修改表单项的内容

修改表单项的内容可以通过直接修改表单项状态来实现。例如,以下代码展示了如何修改表单项的名称。

const modify = (key, newValue) => {
  const itemsCopy = [...items];
  const index = itemsCopy.findIndex((item) => item.key === key);
  itemsCopy[index].value = newValue;
  setItems(itemsCopy);
};

高级功能探索

使用 Form.List 集成验证

Form.List 组件支持与表单验证集成。通过设置 shouldUpdate 属性,可以实现对表单项的实时验证。

<Form.Item
  key={key}
  {...restField}
  shouldUpdate={(prevValues, currentValues) =>
    prevValues.value !== currentValues.value
  }
>
  <Input />
</Form.Item>

与外部数据源的联动

Form.List 组件可以与外部数据源联动,例如在用户输入新的表单项时,可以从服务器获取数据填充表单项。

const add = async () => {
  const response = await fetch('/api/data');
  const newItem = await response.json();
  setItems([...items, newItem]);
};

使用规则控制表单项的展示

通过逻辑判断,可以控制表单项的展示与隐藏。例如,以下代码展示了如何根据表单项的值来决定是否显示或隐藏表单项。

<Form.Item
  key={key}
  {...restField}
  shouldUpdate={(prevValues, currentValues) =>
    prevValues.value !== currentValues.value
  }
>
  {currentValues.value ? <Input /> : null}
</Form.Item>

实际案例分析

案例1:多字段用户信息表单

在一个多字段用户信息表单中,用户可以根据需要添加多个字段,例如多个电话号码或多个地址。以下是一个简单的示例:

import React from 'react';
import { Form, Input, Button, List } from 'antd';

const UserForm = () => {
  const [form] = Form.useForm();
  const [fields, setFields] = React.useState([{ key: '1' }]);

  const addField = () => {
    setFields([...fields, { key: `${fields.length + 1}` }]);
  };

  const removeField = (key) => {
    const fieldsCopy = [...fields];
    const index = fieldsCopy.findIndex((field) => field.key === key);
    fieldsCopy.splice(index, 1);
    setFields(fieldsCopy);
  };

  return (
    <Form form={form}>
      <Form.List name="fields">
        {(fields, { add, remove }) => {
          return (
            <>
              {fields.map((field) => (
                <div key={field.key}>
                  <Form.Item
                    {...field}
                    shouldUpdate={(prevValues, currentValues) =>
                      prevValues.value !== currentValues.value
                    }
                  >
                    <Input />
                  </Form.Item>
                  <Button type="link" onClick={() => remove(field.name)}>
                    删除
                  </Button>
                </div>
              ))}
              <Button type="dashed" onClick={addField} block>
                添加新的输入框
              </Button>
            </>
          );
        }}
      </Form.List>
    </Form>
  );
};

export default UserForm;

案例2:动态添加购物车商品

在一个动态购物车商品表单中,用户可以通过点击按钮添加新的商品项,并且可以删除已有的商品项。

import React from 'react';
import { Form, Input, Button, List } from 'antd';

const ShoppingCartForm = () => {
  const [form] = Form.useForm();
  const [items, setItems] = React.useState([{ key: '1' }]);

  const addItem = () => {
    setItems([...items, { key: `${items.length + 1}` }]);
  };

  const removeItem = (key) => {
    const itemsCopy = [...items];
    const index = itemsCopy.findIndex((item) => item.key === key);
    itemsCopy.splice(index, 1);
    setItems(itemsCopy);
  };

  return (
    <Form form={form}>
      <Form.List name="items">
        {(fields, { add, remove }) => {
          return (
            <>
              {fields.map(({ key, name, fieldKey, ...restField }) => (
                <div key={key}>
                  <Form.Item
                    {...restField}
                    shouldUpdate={(prevValues, currentValues) =>
                      prevValues.value !== currentValues.value
                    }
                  >
                    <Input />
                  </Form.Item>
                  <Button type="link" onClick={() => remove(key)}>
                    删除
                  </Button>
                </div>
              ))}
              <Button type="dashed" onClick={addItem} block>
                添加新的商品
              </Button>
            </>
          );
        }}
      </Form.List>
    </Form>
  );
};

export default ShoppingCartForm;

案例3:复杂问卷表单生成

在一个复杂问卷表单中,用户可以根据需要添加多个问题,并且每个问题可以有不同的输入类型,例如选择题、填空题等。

import React from 'react';
import { Form, Input, Radio, Checkbox, List } from 'antd';

const SurveyForm = () => {
  const [form] = Form.useForm();
  const [questions, setQuestions] = React.useState([{ key: '1' }]);

  const addQuestion = () => {
    setQuestions([...questions, { key: `${questions.length + 1}` }]);
  };

  const removeQuestion = (key) => {
    const questionsCopy = [...questions];
    const index = questionsCopy.findIndex((question) => question.key === key);
    questionsCopy.splice(index, 1);
    setQuestions(questionsCopy);
  };

  return (
    <Form form={form}>
      <Form.List name="questions">
        {(fields, { add, remove }) => {
          return (
            <>
              {fields.map(({ key, name, fieldKey, ...restField }) => (
                <div key={key}>
                  <Form.Item
                    {...restField}
                    shouldUpdate={(prevValues, currentValues) =>
                      prevValues.value !== currentValues.value
                    }
                  >
                    <Input />
                  </Form.Item>
                  <Form.Item
                    {...restField}
                    shouldUpdate={(prevValues, currentValues) =>
                      prevValues.type !== currentValues.type
                    }
                  >
                    <Radio.Group>
                      <Radio value="single">单选题</Radio>
                      <Radio value="multiple">多选题</Radio>
                    </Radio.Group>
                  </Form.Item>
                  <Button type="link" onClick={() => remove(key)}>
                    删除
                  </Button>
                </div>
              ))}
              <Button type="dashed" onClick={addQuestion} block>
                添加新的问题
              </Button>
            </>
          );
        }}
      </Form.List>
    </Form>
  );
};

export default SurveyForm;

常见问题及解决方案

常见的错误和解决方法

  1. 表单项显示异常
    • 确保每个表单项都有唯一的 key 属性。
    • 检查 Form.Listname 属性是否正确配置。
<Form.List name="items">
  {(fields, { add, remove }) => {
    return (
      <>
        {fields.map((field) => (
          <Form.Item key={field.key} {...field}>
            <Input />
          </Form.Item>
        ))}
        <Button type="dashed" onClick={add} block>
          添加新的输入框
        </Button>
      </>
    );
  }}
</Form.List>
  1. 动态添加的表单项无法获取值
    • 确保在表单项中使用 key 属性,并且确保 Form.Listname 属性正确配置。
    • 检查在提交表单时是否正确获取了表单项的值。
const onFinish = (values) => {
  console.log(values);
};

性能优化技巧

  1. 减少不必要的重新渲染
    • 使用 React.memouseMemo 高阶组件来优化性能。
    • 使用 shouldComponentUpdateReact.PureComponent 来避免不必要的重新渲染。
const MyComponent = React.memo((props) => {
  return <div>{props.value}</div>;
});
  1. 合理使用 key 属性
    • 确保每个表单项的 key 属性是唯一的。
    • 尽量避免使用动态生成的 key,因为这会导致不必要的重新渲染。

社区资源与帮助

  • 官方文档: Ant Design 的官方网站提供了详细的文档和示例,帮助你更好地理解和使用 Form.List 组件。
  • 社区支持: 可以加入 Ant Design 的官方论坛或社区,与其他开发者交流经验和解决方案。
  • 在线课程: 慕课网 提供了丰富的课程和视频,帮助你快速掌握 Form.List 组件的使用技巧和最佳实践。

以上内容详细介绍了 Form.List 组件的基本使用方法、高级功能和典型案例,希望能帮助你轻松掌握动态表单的构建技巧。

0人推荐
随时随地看视频
慕课网APP