Skip to content

leonwgc/antd-form-render

Repository files navigation

🚀 Antd Form Render

基于配置的 Ant Design 表单渲染器

npm version npm downloads license typescript

English | 简体中文

📖 在线示例 | 🐛 报告问题


✨ 特性

  • 🎯 配置驱动 - 使用简洁的 JavaScript 配置构建复杂表单
  • 🎨 多种布局 - 支持 Grid、Flex、Space 三种灵活布局方式
  • 🔄 数据驱动 - 遵循 React 理念 UI = F(state),轻松实现表单联动
  • 🪝 Hooks 优先 - 基于 React Hooks,完美适配现代 React 开发
  • 📘 TypeScript - 完整的类型定义,提供出色的开发体验
  • ⚡️ 轻量高效 - 核心代码简洁,零额外依赖
  • 🎭 灵活扩展 - 支持自定义渲染,满足各种业务场景

📦 安装

# npm
npm install antd-form-render

# yarn
yarn add antd-form-render

# pnpm
pnpm add antd-form-render

注意: 需要在项目中安装 antd >= 4.0.0react >= 16.8.0

🎯 快速开始

基础用法

import React from 'react';
import { Form, Button, Input } from 'antd';
import { GridRender } from 'antd-form-render';

const App = () => {
  const [form] = Form.useForm();

  const layout = [
    {
      label: '用户名',
      name: 'username',
      rules: [{ required: true, message: '请输入用户名' }],
      element: <Input placeholder="请输入用户名" />,
    },
    {
      label: '密码',
      name: 'password',
      element: <Input.Password placeholder="请输入密码" />,
    },
    {
      element: (
        <Button type="primary" htmlType="submit">
          提交
        </Button>
      ),
    },
  ];

  const onFinish = (values) => {
    console.log('表单数据:', values);
  };

  return (
    <Form form={form} onFinish={onFinish} layout="vertical">
      <GridRender layout={layout} />
    </Form>
  );
};

export default App;

📚 布局方式

1️⃣ Grid 布局

适合需要严格栅格对齐的表单场景。

单列布局

查看代码
import React from 'react';
import { Form, Button, Input } from 'antd';
import { GridRender } from 'antd-form-render';

const GridOneColumn = () => {
  const [form] = Form.useForm();

  const layout = [
    {
      label: '手机号',
      name: 'tel',
      rules: [{ required: true, message: '请输入手机号' }],
      element: <Input placeholder="请输入" maxLength={11} />,
    },
    {
      label: '密码',
      name: 'pwd',
      element: <Input.Password placeholder="请输入密码" />,
    },
    {
      element: (
        <Button type="primary" htmlType="submit" block>
          保存
        </Button>
      ),
    },
  ];

  return (
    <Form form={form} layout="vertical" style={{ width: 400 }}>
      <GridRender layout={layout} />
    </Form>
  );
};

Grid 单列布局

多列布局

查看代码
import React, { useState } from 'react';
import { Input, Radio, Form } from 'antd';
import { GridRender } from 'antd-form-render';

const GridNColumns = () => {
  const [cols, setCols] = useState(4);
  const layout = Array.from({ length: 11 }, (_, i) => ({
    label: `输入框${i + 1}`,
    name: `name${i}`,
    element: <Input placeholder="请输入" />,
  }));

  return (
    <Form layout="vertical">
      <Radio.Group
        onChange={(e) => setCols(Number(e.target.value))}
        optionType="button"
        value={cols}
        style={{ marginBottom: 24 }}
      >
        <Radio value={1}>1列</Radio>
        <Radio value={2}>2列</Radio>
        <Radio value={3}>3列</Radio>
        <Radio value={4}>4列</Radio>
      </Radio.Group>

      <GridRender layout={layout} columnCount={cols} gutter={[8, 8]} />
    </Form>
  );
};

Grid 多列布局

2️⃣ Space 布局

适合内联或工具栏表单场景。

查看代码
import React, { useState } from 'react';
import { Input, Radio, Form, Button } from 'antd';
import { SpaceRender } from 'antd-form-render';

const SpaceLayout = () => {
  const [form] = Form.useForm();
  const [space, setSpace] = useState(8);

  const layout = [
    ...Array.from({ length: 3 }, (_, i) => ({
      name: `name${i}`,
      label: `输入框${i + 1}`,
      element: <Input placeholder="请输入" />,
    })),
    {
      element: (
        <Button type="primary" onClick={() => console.log(form.getFieldsValue())}>
          提交
        </Button>
      ),
    },
  ];

  return (
    <Form form={form} layout="horizontal">
      <Radio.Group
        onChange={(e) => setSpace(Number(e.target.value))}
        optionType="button"
        value={space}
        style={{ marginBottom: 24 }}
      >
        <Radio value={8}>8px</Radio>
        <Radio value={16}>16px</Radio>
        <Radio value={24}>24px</Radio>
        <Radio value={32}>32px</Radio>
      </Radio.Group>

      <SpaceRender layout={layout} size={space} />
    </Form>
  );
};

Space 布局

3️⃣ Flex 布局

适合需要灵活对齐和分布的表单场景。

查看代码
import React, { useState } from 'react';
import { Input, Radio, Form, Button } from 'antd';
import { FlexRender } from 'antd-form-render';

const FlexLayout = () => {
  const [form] = Form.useForm();
  const [gap, setGap] = useState(8);

  const layout = [
    ...Array.from({ length: 3 }, (_, i) => ({
      name: `name${i}`,
      label: `输入框${i + 1}`,
      element: <Input placeholder="请输入" />,
    })),
    {
      element: (
        <Button type="primary" onClick={() => console.log(form.getFieldsValue())}>
          提交
        </Button>
      ),
    },
  ];

  return (
    <Form form={form} layout="horizontal">
      <Radio.Group
        onChange={(e) => setGap(Number(e.target.value))}
        optionType="button"
        value={gap}
        style={{ marginBottom: 24 }}
      >
        <Radio value={8}>8px</Radio>
        <Radio value={16}>16px</Radio>
        <Radio value={24}>24px</Radio>
        <Radio value={32}>32px</Radio>
      </Radio.Group>

      <FlexRender layout={layout} gap={gap} justify="flex-end" />
    </Form>
  );
};

Flex 布局

🔄 表单联动

实现表单项之间的动态交互有两种方式:

方式一:状态驱动(全量渲染)

通过 onValuesChange 同步表单状态到外部 state,触发重新渲染。

方式二:局部更新(推荐)

利用 Form.Item 的 dependencies / shouldUpdate 和自定义渲染函数,实现按需更新。

查看代码
import React from 'react';
import { Form, Input, Checkbox } from 'antd';
import { GridRender } from 'antd-form-render';

const DynamicRender = () => {
  const [form] = Form.useForm();

  const layout = [
    {
      label: '姓名',
      name: 'name',
      element: <Input placeholder="请输入姓名" />,
    },
    {
      itemProps: { noStyle: true },
      element: () =>
        form.getFieldValue('name') ? (
          <div style={{ marginBottom: 24, color: '#1890ff' }}>
            你好, {form.getFieldValue('name')}!
          </div>
        ) : null,
    },
    {
      label: '喜欢的运动',
      name: 'sports',
      element: <Checkbox.Group options={['篮球', '足球', '排球']} />,
    },
    {
      element: () => {
        const sports = form.getFieldValue('sports');
        return sports?.length ? (
          <div style={{ padding: '12px', background: '#f0f0f0', borderRadius: 4 }}>
            ✅ 你选择了: {sports.join(', ')}
          </div>
        ) : (
          <div style={{ color: '#999' }}>请选择你喜欢的运动</div>
        );
      },
    },
  ];

  return (
    <Form form={form} layout="vertical">
      <GridRender layout={layout} />
    </Form>
  );
};

表单联动

📖 API 文档

Item 配置项

属性 说明 类型 默认值
element React 节点,优先级最高 ReactNode | (() => ReactNode) -
type 组件类型,如 Input、DatePicker ComponentType | string -
name Form.Item 的 name 字段 string | (string | number)[] -
label Form.Item 的 label ReactNode -
rules 表单验证规则 Rule[] -
render 自定义渲染函数 () => ReactNode -
getJSON 动态返回 Item,优先级高于 render () => Item | null -
elProps 透传给组件的 props Record<string, unknown> -
itemProps 透传给 Form.Item 的 props FormItemProps -

GridRender Props

属性 说明 类型 默认值
layout 布局配置数组 Item[] 必填
columnCount 一行的列数 (1-4) number 1
gutter 栅格间距 number | [number, number] 0
...rest 其他 Row 组件的 props RowProps -

SpaceRender Props

属性 说明 类型 默认值
layout 布局配置数组 Item[] 必填
size 间距大小 number | 'small' | 'middle' | 'large' 'small'
direction 排列方向 'horizontal' | 'vertical' 'horizontal'
...rest 其他 Space 组件的 props SpaceProps -

FlexRender Props

属性 说明 类型 默认值
layout 布局配置数组 Item[] 必填
gap 间距大小 number | string -
justify 主轴对齐方式 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' -
align 交叉轴对齐方式 'flex-start' | 'flex-end' | 'center' | 'stretch' -
...rest 其他 Flex 组件的 props FlexProps -

🎯 使用场景

  • 企业后台管理系统 - 快速构建复杂的数据录入表单
  • 搜索过滤器 - 动态配置多条件搜索表单
  • 配置面板 - 可视化的配置项管理
  • 问卷调查 - 动态生成调查问卷表单
  • 数据导入向导 - 多步骤表单流程

🤝 贡献指南

欢迎贡献代码、提出建议或报告问题!

# 克隆仓库
git clone https://github.com/leonwgc/antd-form-render.git

# 安装依赖
npm install

# 启动开发服务器
npm start

# 构建
npm run build

📄 许可证

MIT © leonwgc


用 ❤️ 构建

About

使用 js 配置开发 ant-design 表单

Resources

Stars

Watchers

Forks

Packages

No packages published