假如你点开了这篇文章,相信你是一个有经历的前端开发了,造轮子或许现已不能满足咱们的成就感了。想当初我吭哧吭哧做了一套Angular的组件库别提多开心了,但是毕竟是自己一个人短期内开发出来的,也只要input,select之类的几个根底组件,前端小伙伴又凭什么甘愿抛弃现有的成熟的组件库,转而用我的呢?既然AntDesign这样的组件库现已如此成熟,我又何必班门弄斧?但我发现一个缝隙求生的当地,像AntDesign,SemiDesign,MuiDesign这类组件库,实质是界说的款式,许多组件拿到项目中,仍是需求封装一遍,尤其是做简化代码甚至低代码的工作中,将现有的组件库封装成一个可装备化的组件库就尤为重要了。
咱们在这篇文章中介绍了封装表单组件需求准备哪些特点:封装表单元素,应该界说哪些状况或特点?。咱们能够知道有一些表单元素有共同的特点,有一些有特异性,比方单行文本输入框text input,数字输入框number input,和多行文本输入框textarea都需求监听输入的改动,而select和autocomplete都是以选项的改动来改动值的。
本着“高内聚,低耦合”的主旨,咱们将封装分为不同的层级,这儿我用不同的目录层级来表明,能够参阅右边的纲要。不常用的组件后期我会继续更新,感兴趣能够先保藏。
FreeForm
在form层面,也便是field的外层需求对单个field处理如下特点:
- 【值特点】依据field的
getDefaultValue()
核算好初始值。传递defaultValue
。默许值特点相互之间是有抵触的,后边我会具体规划这其中的优先级。 - 【值特点】假如组件是初始无值的状况,将
defaultValue
赋值给value
。假如组件现已有值,则作为value
。传递value
。 - 【值特点】依据field的
onChange()
改动value
。 - 【值特点】依据field的
onInputChange()
改动inputValue
。 - 【值特点】传递
rootFormValue
。 - 【值特点】传递哪个form里哪个field的值改动了。
- 【操控类特点】依据field的
enabledOn
核算enabled
状况。传递enabled
。 - 【操控类特点】依据field的
visibleOn
核算visible
状况。传递visible
。 - 【操控类特点】依据field的
availableOn
核算available
状况。传递available
。 - 【操控类特点】依据field的
requiredOn
核算required
状况。传递required
。 - 【用户行为类特点】依据field的
onBlur()
改动touched
状况。传递touched
。 - 【用户行为类特点】依据field的
onChange()
改动dirty
状况。传递dirty
。 - 【用户行为类特点】依据field的
onChange()
时value
是否等同于defaultValue
来核算different
状况。传递different
。 - 【用户行为类特点】传递
clearable
,当clearable
为true
时,依据field的onClear()
将value
清空。 - 【用户行为类特点】传递
resettable
,当resettable
为true
时,依据field的onReset()
将value
,inputValue
,touched
,dirty
重置。 - 【用户行为类特点】传递
deletable
,当deletable
为true
时,依据field的onDelete()
将available
改为false
,意味着这个field
不可用,对应的字段将被移除。 - 【辅佐类特点】传递
label
,key
,title
,disabledReason
(disabled时,title选用展现disableReason),helperText
,placeholder
。 - 【辅佐类特点】传递
path
,当有嵌套form时,path
将帮助咱们快速定位到field,比方:univerity.department.class.student.name
。 - 【款式类特点】传递
className
,width
,size
,tabIndex
。 - 【校验类特点】传递
validations
。 - 【校验类特点】传递
errors
。 - 【多组件组合】需求支撑多field+button组合,如下图:
- 【辅佐类特点】传递
label
。 - 【辅佐类特点】传递
key
/name
。 - 【辅佐类特点】传递
title
。 - 【辅佐类特点】传递
helperText
。 - 【辅佐类特点】传递
placeholder
。
const { type, getDefaultValue } = props;
const defaultValue = getDefaultValue(...);
const [value, setValue] = useState(defaultValue);
const [inputValue, setInputValue] = useState(defaultValue);
const enabled = useMemo(() => enabledOn(), [...]);
const visible = useMemo(() => visibleOn(), [...]);
const available = useMemo(() => availableOn(), [...]);
const required = useMemo(() => requiredOn(), [...]);
const [touched, setTouched] = useState(false);
const [dirty, setDirty] = useState(false);
const [different, setDifferent] = useState(false);
const handleChange = (value) => {
setValue(value);
setTouched(true);
setDifferent(!isEqual(value, defaultValue));
}
return <FormControl>
<BaseField
type={type}
value={value}
defaultValue={defaultValue}
label={label}
key={key}
title={title}
disableReason={disableReason}
helperText={helperText}
placeholder={placeholder}
path={path}
className={classname}
width={width} // '200px', '80%'
size={size} // 'sm', 'md', 'lg'
validations={validations}
tabIndex={tabIndex}
onChange={handleChange}
onInputChange={setInputValue}
{...(clearable && {onClear: handleClear})} // 将value清空
{...(resettable && {onClear: handleReset})} // 将value重置为最开始的值(不一定是defaultValue)
{...(deletable && {onClear: handleDelete})} // availble改为false
{...(mentionable && onMention: handleMention)} // @或人
onValidated={handleValidated}
/>
</FormControl>
BaseField
多个BaseField组成FreeForm。面向的是form,假如是面向开发者/运用者,参阅下面的FreeFormField。
<BaseField .../>
- 【值特点】传递value。
- 【值特点】传递defaultValue。
- 【校验类特点】承受validations。将validations的成果经过
onValidated()
回来给form。validations和对应的errors的特点界说见这一篇:正在写。。。 - 【校验类特点】传递
errors
。对独自的field显现错误信息有两种办法,一个是传给原生组件,一个是封装自己的错误款式,这取决于咱们用什么样的组件库。validations和对应的errors的特点界说见这一篇:正在写。。。 - 【校验类特点】传递下面各类field所需的校验类特点。
1. BaseTypeable
打字型输入。这是最基本的组件,后边许多组件都需求这个组件。
<BaseField type=“text” .../> ==> <BaseTypeable type=“text” .../>
<BaseField type="number“ .../> ==> <BaseTypeable type="number“ .../>
<BaseField type="textarea" .../> ==> <BaseTypeable type="textarea" .../>
<BaseField type="password" .../> ==> <BaseTypeable type="password" .../>
承继以上BaseField的一切特点以外,还能够:
- 【值特点】【功用】支撑debounce。value change可挑选防抖,比方用户type一个字符约1s后改动field的值。
- 需求支撑前缀后缀,如下图:
- 【用户行为类】假如deletable为true,供给一个按钮点击回来onDelete()。(clear,reset,delete行为仅回来event,field内部不做值的处理,值的处理在form内,field外处理。)
1-1. BaseText
单行文本输入框。
<BaseTypeable type="text" .../> ==> <BaseText .../>
承继以上BaseTypeable的一切特点以外,还能够:
- 【校验类特点】字数约束,承受
minLength
和maxLength
,传递给adaptor。这两个特点是原生特点,咱们尽量运用原生功用,更高效。 - 【校验类特点】字数显现/倒计数,如下图:
- 【校验类特点】承受
pattern
,传递给adaptor。 - 【用户行为类特点】假如
clearable
为true
,供给一个按钮点击回来onClear()
。 - 【用户行为类特点】假如
resettable
为true
,供给一个按钮点击回来onReset()
。 - 【用户行为类特点】语音输入。(假如你想做得狂拽炫酷吊炸天能够试试)
- 【用户行为类特点】承受
mode
,适用于移动端的原生特点。 - 【值特点】承受
format
1-2. BaseNumber
数字输入框。有加减按钮。
即:
<BaseTypeable type="number" .../> ===> <BaseNumber .../>
承继以上BaseTypeable的一切特点以外,还能够:
- 【操控类特点】可经过键盘操控添加削减,大多数组件库本来就支撑。
- 【校验类特点】承受
max
,min
,和step
,原生功用。 - 【校验类特点】承受
numberType
:integer
,decimal
, - 【值特点】承受
format
格局化数字,比方货币,科学计数法,电话号码,银行卡号,如下图: - 【值特点】支撑高精度,如下图,封装的时候需求装BigInt polyfill。
1-3. BasePassword
暗码输入框,能够挑选显现明文暗码。如下图:
<BaseTypeable type="password" .../> ===> <BasePassword .../>
承继以上BaseTypeable的一切特点以外,还能够:
- 【用户行为类特点】是否能够显现明文暗码。 暗码的报错信息或许不同于其他field,需求显现校验列表,并标出哪些满足了哪些不满足。这部分拜见Password组件。
1-4. BaseTextarea
多行文本输入框。
<BaseTypeable type="textarea" .../> ===> <BaseTextarea .../>
承继以上BaseTypeable的一切特点以外,还能够:
- 【校验类特点】字数约束,承受
minLength
和maxLength
,传递给adaptor。这两个特点是原生特点,咱们尽量运用原生功用,更高效。 - 【校验类特点】字数显现/倒计数,类似于BaseText。
- 【款式类特点】承受
rows
,默许显现多少行。 - 【款式类特点】承受
resizable
,能够自界说输入框巨细。 - 【用户行为类特点】能够mention@或人,mention的特点参阅下面BaseMention组件。
1-5. BaseTags
tag输入框。如下图:
2. BaseBinary
Boolean类的输入。也是根底组件,后边许多复合组件也会用到这儿的组件。
<BaseField type=“radio” .../> ==> <BaseBinary type=“radio” .../>
<BaseField type="checkbox“ .../> ==> <BaseBinary type="checkbox“ .../>
<BaseField type="switch" .../> ==> <BaseBinary type="switch" .../>
承继以上BaseField的一切特点以外,还能够:
- 【值特点】处理change event里的
checked
,改为value
。 - 【值特点】常见多个binary field组合成一个selectable 组件,这儿值的处理需求契合selectable field的用法。
- 【辅佐类特点】
label
是指这个field的label,而binary的单个field也有它们自己的label,具体见下面各个field。传递binary label。
2-1. BaseRadio
单个Radio。一旦勾选无法撤销。
<BaseBinary type="radio" .../> ===> <BaseRadio .../>
承继以上BaseBinary的一切特点以外,还能够:
- 【值特点】回来值为
boolean
。 - 【辅佐类特点】承受
optionLabel
,作为这一个选项的label。
2-2. BaseCheckbox
单个Checkbox。可勾选可撤销,还有一个中心态(依然放在binary里面,因为中心态是给treeSelect这种复合组件用的)。 单个Radio。一旦勾选无法撤销。
<BaseBinary type="checkbox" .../> ===> <BaseCheckbox .../>
承继以上BaseBinary的一切特点以外,还能够:
- 【值特点】承受
ternary
,当ternary
为true
时,值有三种状况,用数字0,1,2表明。不然回来值为boolean
。 - 【辅佐类特点】承受
optionLabel
,作为这一个选项的label。
2-3. BaseSwitch
Switch。如下图:
<BaseBinary type="switch" .../> ===> <BaseSwitch .../>
承继以上BaseBinary的一切特点以外,还能够:
- 【值特点】回来值为
boolean
。 - 【辅佐类特点】承受
labelLeft
,作为显现在左边的label。 - 【辅佐类特点】承受
labelRight
,作为显现在右边的label。大多数情况,只需求labelRight
就能够了。
3. BaseSelectable
挑选类的输入。属于复合组件了,有些会用到上面的根底组件。为了方便TypeScript界说类型,我将带有下拉框的组件分为单选和多选。
<BaseField type=“select” .../> ==> <BaseSelectable type=“select” .../>
<BaseField type="autocomplete“ .../> ==> <BaseSelectable type="autocomplete“ .../>
// <BaseField type="cascader" .../> ==> <BaseSelectable type="cascader" .../> 待定
<BaseField type="treeSelect" .../> ==> <BaseSelectable type="treeSelect" .../>
<BaseField type="radios" .../> ==> <BaseSelectable type="radios" .../>
<BaseField type="checkboxes" .../> ==> <BaseSelectable type="checkboxes" .../>
承继以上BaseField的一切特点以外,还能够:
- 【值特点】单选的值为单个值,多选的值为一个数组。
- 【值特点】承受value,并核算出选项中与之平等的值,即
selectedOption
/selectedOptions
。 - 【值特点】承受
allowValueOutOfValue
,当这个特点为true
时,value改动后有必要是选项中的一个,不然会被还原为上一次的值。考虑到后台或许会有脏数据,value在没做任何改动时仍是能够照本来的value显现。 - 【值特点】承受
getDefaultValue()
,这个办法决议了当某些依靠项(如某些其他field的值,选项)改动时,这个field默许改动value。 - 【值特点】承受
isOptionEqualToValue()
,用这个办法经过value挑选对应的option。 - 【选项类特点】选项类特点较为杂乱,请参阅这一篇文章:正在写。。。
3-1. BaseDropdown
带下拉框的挑选组件。
<BaseField type=“dropdown” multiple={true} .../> ==> <BaseSingleDropdown .../>
<BaseField type=“dropdown” multiple={false} .../> ==> <BaseMultiDropdown .../>
承继以上BaseSelectable的一切特点以外,还能够:
- 【功用】虚拟列表
- 【选项类特点】异步load options时,会有输入状况奉告用户。
3-1-1. BaseSingleDropdown
带下拉框的单选组件。
<BaseSingleDropdown .../>
承继以上BaseDropdown的一切特点以外,还能够:
- 【值特点】当
clearable
为true
时,选项中第一位会为一个带placeholder的空选项:
// options[0]
{
label: '-- Select --',
value: ''
}
这样用户挑选了某些值之后,还能够经过挑选这个值来清空。
2. 【值特点】承受defaultSelectFirst
,当这个特点为true
时,表明初始状况或选项更新后,默许挑选第一个选项。
3-1-2. BaseMultiDropdown
带下拉框的多选组件。
<BaseMultiDropdown .../>
承继以上BaseDropdown的一切特点以外,还能够:
- 【款式类特点】承受
limitTags
参数,界说在输入框里显现多少个选项。 - 【值特点】承受
defaultSelectAll
,意味着默许全选。
3-2. BaseAutocomplete
带下拉框和自动填充的挑选组件。
<BaseField type=“autocomplete” multiple={true} .../> ==> <BaseSingleAutocomplete .../>
<BaseField type=“autocomplete” multiple={false} .../> ==> <BaseMultiAutocomplete .../>
承继以上BaseSelectable的一切特点以外,还能够:
- 【值特点】当
allowValueOutOfValue
为true
时,用户能够自在输入。 - 【值特点】承受
format
,当用户能够自在输入时,假如这个组件值的类型较杂乱,能够经过这个办法得到契合格局要求的值。 - 【选项类特点】承受
optionAddable
,当用户自在输入了一个新值后,能够把这个新值加入到option list中(异步操作会发送恳求,同步操作会存到状况里)。 - 【选项类特点】异步load options时,会有输入状况奉告用户。既能够初始时一次性异步获取options,也能够跟着输入异步获取options。
3-2-1. BaseSingleAutocomplete
带下拉框和自动填充的单选组件。
<BaseSingleAutocomplete .../>
承继以上BaseAutocomplete的一切特点以外,还能够:
- 【值特点】承受clearable,当这个特点为true时,选项中第一位会为一个带placeholder的空选项:
// options[0]
{
label: '-- Select --',
value: ''
}
这样用户挑选了某些值之后,还能够经过挑选这个值来清空。
2. 【值特点】承受defaultSelectFirst
,当这个特点为true
时,表明初始状况或选项更新后,默许挑选第一个选项。
3-2-2. BaseMention
@功用,是由BaseSingleAutocomplete改换而成,type“@”后,跟着输入能够异步查询人名。一般常用在Textarea里。如下图:
<BaseMention .../>
承继以上BaseSingleAutocomplete的大部分特点以外,还能够:
- 【选项类特点】异步获取人员信息,像Jira一样。
- 【值特点】挑选好后,@后边其实仅仅可编辑可删除的文本。
3-2-3. BaseMultiAutocomplete
带下拉框和自动填充的多选组件。
<BaseMultiAutocomplete .../>
承继以上BaseAutocomplete的一切特点以外,还能够:
- 【款式类特点】承受
limitTags
参数,界说在输入框里显现多少个选项。 - 【值特点】承受
defaultSelectAll
,意味着默许全选。
3-3. BaseRadios
Radio组合的单选组件。
<BaseField type=“radios” .../> ==> <BaseRadios .../>
承继以上BaseSelectable的一切特点以外,还能够:
- 【选项类特点】承受’optionsDirection’,界说options的摆放方向,是横向仍是笔直,
row
仍是column
。
3-4. BaseCheckboxes
Checkbox组合的多选组件。
<BaseField type=“checkboxes” .../> ==> <BaseCheckboxes .../>
承继以上BaseSelectable的一切特点以外,还能够:
- 【选项类特点】承受’optionsDirection’,界说options的摆放方向,是横向仍是笔直,
row
仍是column
。
3-5. BaseTreeDropdown
下拉框是树组件的挑选组件。
<BaseField type=“tree” multiple={false} .../> ==> <BaseSingleTreeDropdown .../>
<BaseField type=“tree” multiple={true} .../> ==> <BaseMultiTreeDropdown .../>
承继以上BaseSelectable的一切特点以外,还能够:
- 【选项类特点】承受searchable,类似autocomplete组件,能够将带有关键字的节点挑选出来。
- 【选项类特点】父节点翻开时能够界说
lazyload
,异步获取子节点。
3-5-1. BaseTree
根底的树组件,独立存在,不在下拉框里。假如BaseTreeDropdown的searchable
为false
,则选用这个组件。
<BaseSingleTreeDropdown searchable={false}.../> 封装 <BaseSearchTree .../>
<BaseMultiTreeDropdown searchable={false}.../> 封装 <BaseSearchTree .../>
树组件需求带有select功用,具体规划参阅这篇文章:正在写。。。
3-5-2. BaseSearchTree
带搜索功用的树组件,独立存在,不在下拉框里。将BaseTree与搜索框封装在了一同。假如BaseTreeDropdown的searchable
为true
,则选用这个组件。
<BaseSingleTreeDropdown searchable={true}.../> 封装 <BaseSearchTree .../>
<BaseMultiTreeDropdown searchable={true}.../> 封装 <BaseSearchTree .../>
3-5-3. BaseSingleTreeDropdown
下拉框是树组件的单选组件。
<BaseSingleTreeDropdown .../>
3-5-4. BaseMultiTreeDropdown
下拉框是树组件的多选组件。
<BaseMultiTreeDropdown .../>
4. BaseFile
文件上传组件。能够经过翻开文件体系挑选,也能够拖拽上传,也能够组合起来。
<BaseField type=“fileSelect” .../> ==> <BaseFile type=“fileSelect” .../>
<BaseField type="fileArea“ .../> ==> <BaseFile type="fileArea“ .../>
<BaseField type="fileReview“ .../> ==> <BaseFile type="fileReview“ .../>
承继以上BaseField的一切特点以外,还能够:
- 【值特点】假如是已有值,需求用到BaseFileReview。
- 【值特点】界说file的值,需求区分文件本身和文件名。
- 【值特点】承受
multiple
,能够挑选单文件仍是多文件上传。 - 【校验类特点】承受
accept
,约束上传的文件类型。 - 【校验类特点】承受
maxSize
,约束上传的文件巨细。 - 【用户行为类特点】上传的办法,文件切片,是否能够中止或继续。
- 【款式类特点】上传过程中,是进度条仍是圆环。
4-1. BaseFileSelect
输入框式的文件挑选器。
<BaseFile type=“fileSelect” .../> ==> <BaseFileSelect .../>
承继以上BaseFile的一切特点
4-2. BaseFileArea
Drag & Drop式的文件上传。
<BaseFile type=“fileArea” .../> ==> <BaseFileArea .../>
承继以上BaseFile的一切特点以外,还能够:
- 【款式类特点】承受
size
,拖拽区域的巨细。
4-3. BaseFileReview
上传后的文件预览。这个组件不属于formField组件,仅用来展现。
<BaseFile type=“fileReview” .../> ==> <BaseFileReview .../>
5. BaseMoment
日期时刻挑选组件。
<BaseField type=“date” .../> ==> <BaseMoment type=“date” .../>
<BaseField type=“week” .../> ==> <BaseMoment type=“week” .../>
<BaseField type=“month” .../> ==> <BaseMoment type=“month” .../>
<BaseField type=“time” .../> ==> <BaseMoment type=“time” .../>
<BaseField type=“datetime” .../> ==> <BaseMoment type=“datetime” .../>
承继以上BaseField的一切特点以外,还能够:
- 【值特点】承受
format
,比方:'DD MMM YYYY'
。
5-1. BaseDate
挑选日期。
<BaseMoment type=“date” .../> ==> <BaseDate .../>
承继以上BaseMoment的一切特点
5-2. BaseWeek
挑选周。
<BaseMoment type=“week” .../> ==> <BaseWeek .../>
承继以上BaseMoment的一切特点
5-3. BaseMonth
挑选月。
<BaseMoment type=“month” .../> ==> <BaseMonth .../>
承继以上BaseMoment的一切特点
5-4. BaseTime
挑选时刻。
<BaseMoment type=“time” .../> ==> <BaseTime .../>
承继以上BaseMoment的一切特点
5-5. BaseDateTime
挑选日期和时刻。
<BaseMoment type=“datetime” .../> ==> <BaseDateTime .../>
承继以上BaseMoment的一切特点
6. BaseRange
规模类组件,field值会是包含两个值的数组。
<BaseField type="dateRange" .../> ==> <BaseRange type="dateRange" .../>
<BaseField type="numberRange" .../> ==> <BaseRange type="numberRange" .../>
承继以上BaseField的一切特点
6-1. BaseDateRange
日期规模。
<BaseRange type="dateRange" .../> ==> <BaseDateRange />
承继以上BaseRange的一切特点
6-2. BaseNumberRange
日期规模。
<BaseRange type="numberRange" .../> ==> <BaseNumberRange />
承继以上BaseRange的一切特点
7. BaseSlider
滑块组件,field值会是单个数字,或是数字数组。
<BaseField type="slider" .../> ==> <BaseSlider .../>
承继以上BaseField的一切特点
8. BaseColor
色彩挑选器。
<BaseField type="color" .../> ==> <BaseColor .../>
承继以上BaseField的一切特点
9. BaseRating
五星好评挑选器。
<BaseField type="rating" .../> ==> <BaseRating .../>
承继以上BaseField的一切特点
FormField
以上BaseField是放在FreeForm里运转的,form中会核算值,做校验等操作,并不适合独自拿出来运用,为了能让开发者更方便地运用form field,需求将每个BaseField封装成FormField,比方BaseText,开发者能够独自运用Text组件,BaseSingleDropdown对应SingleDropdown,这样做的优点如下:
- 这样的组件现已将值核算和校验等操作封装在其中了,开发者运用起来会十分轻松。
- 有利于做集成测验。
- 有利于写开发文档。
- 给未来假如需求将组件做成动态组件做准备。
总结
咱们开发的要点并不是在组件本身,事实上,我计划直接用现有的组件库,由于需求通用不同的组件库,每个组件库对应的接口不同,因此需求特制Adaptor,比方在咱们的框架中格局化办法叫“format”,而某个组件库的同样功用的办法名叫“formatter”,另一个组件库这个办法名叫“formateValue”,这样Adaptor的重要性就在于此,仅仅仅仅经过改换姓名,将不同的组件库接入进来,这种办法也是coding浪费最少的办法了。
具体Adaptor的规划这在写。。。
接下来,是FreeForm和FormArray的封装:正在写。。。