背景
在 ToB 场景中,需要录入众多数据,一个表单字段可能数十个,如果每个字段都写一个jsx 组件来表示,那代码量会瞬间臃肿涨至一两千行,维护起来极其不方便。因此需要一个“表单生成器”,在提高代码复用性同时也能极大提高工作效率。 为此参考了XRender 后写了一个简易版本的 FormRender 组件,分享一下使用方法以及实现思路。
开始使用
demo 地址: github.com/hexianzhi/t…
最简使用 demo:
import { Button, View } from "@tarojs/components";
import React, { useRef, useState } from "react";
import FormRender from "../../compoments/formRender";
import "./index.scss";
const formData = [
{
key: "a",
title: "地址",
type: "input",
required: true,
typeProps: {
placeholder: "请输入",
},
},
{
key: "c",
title: "国家",
type: "picker",
typeProps: {
mode: "selector",
range: ["美国", "中国", "巴西", "日本"],
},
},
{
key: "b",
title: "备注",
type: "textarea",
},
];
export default function (props) {
const formRef = useRef<any>();
const [formValue, setformValue] = useState({});
const [formSchema, setformSchema] = useState(formData);
const onChange = (newValue) => {
setformValue(newValue);
};
const onSubmit = () => {
const isValid = formRef.current.validate();
console.log("isValid: ", isValid);
};
return (
<View className="index">
<FormRender
ref={formRef}
formValue={formValue}
formSchema={formSchema}
onChange={onChange}
></FormRender>
<Button onClick={onSubmit}>提交</Button>
</View>
);
}
效果图:
更多用法可以查看 complex.tsx 文件
基本使用思路
formSchema必填,用于描述表单信息。映射成JSX,即以前描述一个表单组件用 JSX,现在用对象来表示。如何修改:
- 外部组件
setState - 内部组件引起的改动:在
formSchema中设置回调,回调中调用外部组件中的setState。比如picker元素中的onColumnChange。 如果formSchema放在单独文件中,函数组件可以通过传递 setState 方法让回调调用,类组件一样但也可以通过绑定 this 的方式调用
formValue为表单值,这两个字段均由外部组件控制。如何修改:
- onChange 回调
-
校验可通过
validate方法,validate会通过校验formSchema中定义的规则
formSchema 规范
具体说明可查看组件 type.d.ts 文件中的 IFormSchema 类型定义,以下为扩展说明
-
type字段决定了使用哪个组件来渲染, 组件必须要在widgets文件夹下声明并导出。 -
required和rules字段用于做校验判断。rules为对象数组,可书写多个校验规则。支持pattern正则以及validate函数形式,其中message为提示信息。 -
title、diabled、required、hidden字段支持布尔值以及函数形式。可在SupportFunctionItem添加其他字段支持 -
title、diabled、required、hidden字段会展开作为第一级字段注入到自定义组件中。可在injectCompKeys添加其他字段支持 -
typeProps字段用于补充组件支持的更为细致的属性,可自行展开或者使用高阶组件withItemToProps展开。 -
render为函数,配合type = custom使用, 返回JSX用于自定义组件。 -
extra用于在元素下展示更多说明信息 -
任意其他字段会传递给自定义组件,可以根据需要自行魔改
如何扩展组件
- 先写好项目组件,然后在
widgets文件夹下引入项目组件并注入value等信息并导出即可,相关props可查看IWidgetProps接口 schema中的custom函数中返回JSX元素
重置样式应该统一在 index.scss做
注意事项
- 组件使用
React.meomo进行性能优化,因此在更改formSchema中注意深克隆对象进行更改对象,如果直接更改formSchema中的对象会导致对比函数中的 pre props 和 current props 一致,进而无法重新渲染 。(当然去掉 React.memo 也可以)
TODO
- 性能优化,组件独立渲染互不干扰