自定义组件
开发前须知
开发支持 Drip Form 的自定义组件前,需要了解以下概念
- 必须了解的概念(基础)
Drip Form
表单控件组成- 组件 props
useField
hook
- 可选了解的概念(进阶)
- 表单模式
useQuery
hookdisptach
用法
Drip Form 表单控件组成
在开发支持 Drip Form
使用的表单控件前,首先需要了解 Drip Form
表单控件的组成部分。
Drip Form
实现了标题、提示、布局(宽度、间距),所以我们只需要开发表单组件部分。
组件 props
必传 props:在每个 Drip Form
自定义组件中都可以获取到
必传 props
export declare type CommonProps = {
//表单绑定的数据key
fieldKey: string
//表单的数据
fieldData: any
//操作全局状态的方法
dispatch: Dispatch
/**
* 获取fieldKey在unitedSchema、uiSchema、dataSchema中的路径
* 用于配合dispatch修改全局状态
*/
getKey: GetKey
}
- dispatch 用法参考下面介绍;
- getKey 的用法详细查看:API getKey
可选 props:Drip Form
自定义组件中不一定获取到
可选 props 是否可以获取到取决于以下外部配置
- unitedSchema 中表单控件 ui 的配置
- Drip Form props 的配置
可选 props
declare type DripFormEventType = {
type: string
payload: any
}
declare type DripFormEventFuncType = (event: DripFormEventType) => any
export declare type Props = Partial<{
//unitedSchema中ui.style字段
style: CSSProperties
//用户无需关心,传递给useField
onChange: string
//用户无需关心,传递给useQuery
queryFunc: (...args: any[]) => any
//用户无需关心,传递给useQuery
requestCache: boolean
/**
* 当前表单的模式
* edit:当前表单为编辑模式
* generator:当前表单是在form-generator的拖拽区域中
* view:当前表单为只读模式
*/
formMode: 'edit' | 'generator' | 'view'
// onEvent的事件注册
fireEvent: DripFormEventFuncType
}>
useField
参考下面介绍:useQuery
参考下面介绍;formMode
参考下面表单模式介绍:fireEvent
用法详细参考:API onEvent
useField hook
Drip Form
在组件顶层存放了所有表单数据 formData
。每个表单通过 props 中的fieldData
和 fieldKey
对全局数据进行修改。
为了方便用户修改,通过 useField hook 可以快速生成修改当前表单数据的回调函数。
- 事件中使用
- 直接传递值
import { useField } from '@jdfed/hooks'
import { Input } from 'antd'
const CustomComponent = ({ fieldKey, onChange, getKey, dispatch }) => {
const _onChange = useField(
{
fieldKey,
getKey,
onChange,
},
dispatch
)
<Input onChange={_onChange} />
}
import { useCallback } from 'react'
import { useField } from '@jdfed/hooks'
import { Input } from 'antd'
const CustomComponent = ({ fieldKey, onChange, getKey, dispatch }) => {
const _onChange = useField(
{
fieldKey,
getKey,
onChange,
},
dispatch
)
const changeFn = useCallback(()=>{
// 设置固定的值
_onChange(xxxx)
},[_onChange])
<Input onChange={changeFn} />
}
useField 详细介绍参考:API useField
如果有一些自定义校验、自定义修改数据的需求,可通过dispatch进行修改。
表单模式(进阶)
自定义组件可以针对不同的
formMode
开发不同的模式
Drip Form
有以下两种常用模式
edit
编辑模式view
查看模式(只读,不可修改数据)
formMode
还有另一个选项 generator
,表示表单在表单生成器的拖拽区域中,用户无需使用该模式)
针对不同formMode,渲染不同模式
import React, { memo } from 'react'
import { InputNumber } from 'antd'
import { useField } from '@jdfed/hooks'
const NumberField = ({
onChange,
fieldData,
fieldKey,
dispatch,
getKey,
formMode,
...restProps
}) => {
const _onChange = useField(
{ fieldKey, onChange, getKey },
dispatch
)
// 查看 模式
if (formMode === 'view') return fieldData || null
// 编辑模式
return (
<InputNumber
onChange={_onChange}
value={fieldData}
{...restProps}
/>
)
}
export const numberField = memo(NumberField)
useQuery hook(进阶)
useQuery
用来调用onQuery
中返回的数据,并将数据设置到ui.options
中
useQuery 详细介绍参考:API useQuery
dispatch 用法(进阶)
当组件存在自定义校验场景、特定情况需要修改其他表单数据时可使用
dispatch
。
dispatch 详细介绍参考:API dispatch
开发
开发一个数字输入框组件
代码示例
import React, { memo } from 'react'
import { InputNumber } from 'antd'
import { useField } from '@jdfed/hooks'
const NumberField = ({
onChange,
fieldData,
fieldKey,
dispatch,
getKey,
formMode,
...restProps
}) => {
const _onChange = useField(
{ fieldKey, onChange, getKey },
dispatch
)
// view 查看模式
if (formMode === 'view') return fieldData || null
// edit 编辑模式
return (
<InputNumber
onChange={_onChange}
value={fieldData}
{...restProps}
/>
)
}
export const numberField = memo(NumberField)
使用
如何在 Drip Form 中使用开发的自定义组件?
Drip Form
有两种导入自定义组件的方法。
- 使用 customComponets
- 使用 主题
可以根据自定义组件的使用程度、组件是否需要复用来选择使用哪种方法。
- 自定义组件只在当前表单使用,则使用 customComponents 导入使用;
- 自定义组件后续可能在其他场景或表单中使用,则使用 主题;
使用 customComponets
代码示例
- App.tsx
- numberField
- unitedSchema
import DripForm from '@jdfed/drip-form';
import antd from '@jdfed/drip-form-theme-antd';
import unitedSchema from './unitedSchema';
import { numberField } from './numberField';
import '@jdfed/drip-form/dist/index.css';
import '@jdfed/drip-form-theme-antd/dist/index.css';
import 'antd/dist/antd.css';
// 需要和fieldKey一致
const customComponents = {
number_lAjBzU: numberField,
number_QmKL9J: numberField,
};
function App() {
return (
<DripForm
// 表单配置文件
unitedSchema={unitedSchema}
// 导入antd主题
uiComponents={{ antd }}
//导入自定义组件
customComponents={customComponents}
></DripForm>
);
}
export default App;
/**
* 自定义nubmer组件
*/
import { memo } from 'react';
import { InputNumber } from 'antd';
import { useField } from '@jdfed/hooks';
import { CommonProps } from './global';
const NumberField = ({
onChange,
fieldData,
fieldKey,
dispatch,
getKey,
formMode,
...restProps
}: CommonProps) => {
const _onChange = useField({ fieldKey, onChange, getKey }, dispatch);
// view 查看模式
if (formMode === 'view') return fieldData || null;
// edit 编辑模式
return <InputNumber onChange={_onChange} value={fieldData} {...restProps} />;
};
export const numberField = memo(NumberField);
export default {
type: 'object',
showError: 'change',
ui: {},
theme: 'antd',
schema: [
{
type: 'string',
title: '输入框',
ui: {
type: 'text',
style: {
width: '100%',
},
},
fieldKey: 'text_5oOHZr',
},
{
type: 'number',
title: '数字输入框1',
ui: {
type: 'custom',
description: {
type: 'text',
title: '第一次使用number自定义组件',
},
},
fieldKey: 'number_lAjBzU',
},
{
type: 'number',
title: '数字输入框2',
ui: {
type: 'custom',
description: {
type: 'text',
title: '第二次使用number自定义组件',
},
},
fieldKey: 'number_QmKL9J',
},
],
};
- 使用
customComponets
导入自定义组件,会使该自定义组件无法复用。 - 数组容器中,无法使用
customComponents
导入的自定义组件。 因为无法复用,详情查看数组容器如何使用自定义组件?
使用主题
两个步骤快速使用主题
将自定义组件变成自定义主题中的一个控件
自定义主题开发查看文档: 自定义主题
导入主题
代码示例
- App.tsx
- customTheme/numberField.tsx
- customTheme/index.ts
- unitedSchema
/**
* 使用主题导入自定义组件例子
* 优点:组件可以重复使用,并且主题可以单独发布npm包,跨业务使用。
*/
import DripForm from '@jdfed/drip-form';
import antd from '@jdfed/drip-form-theme-antd';
import unitedSchema from './unitedSchema';
import customTheme from './customTheme';
import '@jdfed/drip-form/dist/index.css';
import '@jdfed/drip-form-theme-antd/dist/index.css';
import 'antd/dist/antd.css';
function App() {
return (
<DripForm
// 表单配置文件
unitedSchema={unitedSchema}
// 导入antd主题和自定义主题customTheme
uiComponents={{ antd, customTheme }}
></DripForm>
);
}
export default App;
/**
* 自定义nubmer组件
*/
import { memo } from 'react';
import { InputNumber } from 'antd';
import { useField } from '@jdfed/hooks';
import { CommonProps } from '../global';
const NumberField = ({
onChange,
fieldData,
fieldKey,
dispatch,
getKey,
formMode,
...restProps
}: CommonProps) => {
const _onChange = useField({ fieldKey, onChange, getKey }, dispatch);
// view 查看模式
if (formMode === 'view') return fieldData || null;
// edit 编辑模式
return <InputNumber onChange={_onChange} value={fieldData} {...restProps} />;
};
export const numberField = memo(NumberField);
/**
* 导出自定义主题 customTheme
*/
import { numberField } from './numberField';
export default {
number: numberField,
// 自定义主题名字,随意取
theme: 'customTheme',
};
// 表单配置文件
export default {
type: 'object',
showError: 'change',
ui: {},
theme: 'antd',
schema: [
{
type: 'string',
title: '输入框',
ui: {
type: 'text',
style: {
width: '100%',
},
},
fieldKey: 'text_5oOHZr',
},
{
type: 'number',
title: '数字输入框1',
ui: {
// 需要和自定义主题名字一致
theme: 'customTheme',
type: 'number',
description: {
type: 'text',
title: '第一次使用number自定义组件',
},
},
fieldKey: 'number_lAjBzU',
},
{
type: 'number',
title: '数字输入框2',
ui: {
// 需要和自定义主题名字一致
theme: 'customTheme',
type: 'number',
description: {
type: 'text',
title: '第二次使用number自定义组件',
},
},
fieldKey: 'number_QmKL9J',
},
],
};
开发注意事项
如果需要支持在表单生成器中拖拽生成,建议同时配置config文件。
config文件配置参考 表单生成器文档
注意添加
React memo
避免不必要的渲染。