假如你点开了这篇文章,相信你是一个有经历的前端开发了,造轮子或许现已不能满足咱们的成就感了。想当初我吭哧吭哧做了一套Angular的组件库别提多开心了,但是毕竟是自己一个人短期内开发出来的,也只要input,select之类的几个根底组件,前端小伙伴又凭什么甘愿抛弃现有的成熟的组件库,转而用我的呢?既然AntDesign这样的组件库现已如此成熟,我又何必班门弄斧?但我发现一个缝隙求生的当地,像AntDesign,SemiDesign,MuiDesign这类组件库,实质是界说的款式,许多组件拿到项目中,仍是需求封装一遍,尤其是做简化代码甚至低代码的工作中,将现有的组件库封装成一个可装备化的组件库就尤为重要了。

咱们在这篇文章中介绍了封装表单组件需求准备哪些特点:封装表单元素,应该界说哪些状况或特点?。咱们能够知道有一些表单元素有共同的特点,有一些有特异性,比方单行文本输入框text input,数字输入框number input,和多行文本输入框textarea都需求监听输入的改动,而select和autocomplete都是以选项的改动来改动值的。

本着“高内聚,低耦合”的主旨,咱们将封装分为不同的层级,这儿我用不同的目录层级来表明,能够参阅右边的纲要。不常用的组件后期我会继续更新,感兴趣能够先保藏。

FreeForm

在form层面,也便是field的外层需求对单个field处理如下特点:

  1. 【值特点】依据field的getDefaultValue()核算好初始值。传递defaultValue。默许值特点相互之间是有抵触的,后边我会具体规划这其中的优先级。
  2. 【值特点】假如组件是初始无值的状况,将defaultValue赋值给value。假如组件现已有值,则作为value。传递value
  3. 【值特点】依据field的onChange()改动value
  4. 【值特点】依据field的onInputChange()改动inputValue
  5. 【值特点】传递rootFormValue
  6. 【值特点】传递哪个form里哪个field的值改动了。
  7. 【操控类特点】依据field的enabledOn核算enabled状况。传递enabled
  8. 【操控类特点】依据field的visibleOn核算visible状况。传递visible
  9. 【操控类特点】依据field的availableOn核算available状况。传递available
  10. 【操控类特点】依据field的requiredOn核算required状况。传递required
  11. 【用户行为类特点】依据field的onBlur()改动touched状况。传递touched
  12. 【用户行为类特点】依据field的onChange()改动dirty状况。传递dirty
  13. 【用户行为类特点】依据field的onChange()value是否等同于defaultValue来核算different状况。传递different
  14. 【用户行为类特点】传递clearable,当clearabletrue时,依据field的onClear()value清空。
  15. 【用户行为类特点】传递resettable,当resettabletrue时,依据field的onReset()valueinputValuetoucheddirty重置。
  16. 【用户行为类特点】传递deletable,当deletabletrue时,依据field的onDelete()available改为false,意味着这个field不可用,对应的字段将被移除。
  17. 【辅佐类特点】传递labelkeytitledisabledReason(disabled时,title选用展现disableReason), helperTextplaceholder
  18. 【辅佐类特点】传递path,当有嵌套form时,path将帮助咱们快速定位到field,比方:univerity.department.class.student.name
  19. 【款式类特点】传递classNamewidthsizetabIndex
  20. 【校验类特点】传递validations
  21. 【校验类特点】传递errors
  22. 【多组件组合】需求支撑多field+button组合,如下图:
    封装表单元素的架构规划

    封装表单元素的架构规划
  23. 【辅佐类特点】传递label
  24. 【辅佐类特点】传递key/name
  25. 【辅佐类特点】传递title
  26. 【辅佐类特点】传递helperText
  27. 【辅佐类特点】传递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 .../>
  1. 【值特点】传递value。
  2. 【值特点】传递defaultValue。
  3. 【校验类特点】承受validations。将validations的成果经过onValidated()回来给form。validations和对应的errors的特点界说见这一篇:正在写。。。
  4. 【校验类特点】传递errors。对独自的field显现错误信息有两种办法,一个是传给原生组件,一个是封装自己的错误款式,这取决于咱们用什么样的组件库。validations和对应的errors的特点界说见这一篇:正在写。。。
  5. 【校验类特点】传递下面各类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的一切特点以外,还能够:

  1. 【值特点】【功用】支撑debounce。value change可挑选防抖,比方用户type一个字符约1s后改动field的值。
  2. 需求支撑前缀后缀,如下图:
    封装表单元素的架构规划
    封装表单元素的架构规划
  3. 【用户行为类】假如deletable为true,供给一个按钮点击回来onDelete()。(clear,reset,delete行为仅回来event,field内部不做值的处理,值的处理在form内,field外处理。)

1-1. BaseText

单行文本输入框。

<BaseTypeable type="text" .../> ==> <BaseText .../>

承继以上BaseTypeable的一切特点以外,还能够:

  1. 【校验类特点】字数约束,承受minLengthmaxLength,传递给adaptor。这两个特点是原生特点,咱们尽量运用原生功用,更高效。
  2. 【校验类特点】字数显现/倒计数,如下图:
    封装表单元素的架构规划
  3. 【校验类特点】承受pattern,传递给adaptor。
  4. 【用户行为类特点】假如clearabletrue,供给一个按钮点击回来onClear()
  5. 【用户行为类特点】假如resettabletrue,供给一个按钮点击回来onReset()
  6. 【用户行为类特点】语音输入。(假如你想做得狂拽炫酷吊炸天能够试试)
  7. 【用户行为类特点】承受mode,适用于移动端的原生特点。
  8. 【值特点】承受format

1-2. BaseNumber

数字输入框。有加减按钮。
即:

<BaseTypeable type="number" .../> ===> <BaseNumber .../>

承继以上BaseTypeable的一切特点以外,还能够:

  1. 【操控类特点】可经过键盘操控添加削减,大多数组件库本来就支撑。
  2. 【校验类特点】承受maxmin,和step,原生功用。
  3. 【校验类特点】承受numberType: integer, decimal,
  4. 【值特点】承受format格局化数字,比方货币,科学计数法,电话号码,银行卡号,如下图:
    封装表单元素的架构规划
  5. 【值特点】支撑高精度,如下图,封装的时候需求装BigInt polyfill。
    封装表单元素的架构规划

1-3. BasePassword

暗码输入框,能够挑选显现明文暗码。如下图:

封装表单元素的架构规划

<BaseTypeable type="password" .../> ===> <BasePassword .../>

承继以上BaseTypeable的一切特点以外,还能够:

  1. 【用户行为类特点】是否能够显现明文暗码。 暗码的报错信息或许不同于其他field,需求显现校验列表,并标出哪些满足了哪些不满足。这部分拜见Password组件。

1-4. BaseTextarea

多行文本输入框。

<BaseTypeable type="textarea" .../> ===> <BaseTextarea .../>

承继以上BaseTypeable的一切特点以外,还能够:

  1. 【校验类特点】字数约束,承受minLengthmaxLength,传递给adaptor。这两个特点是原生特点,咱们尽量运用原生功用,更高效。
  2. 【校验类特点】字数显现/倒计数,类似于BaseText。
  3. 【款式类特点】承受rows,默许显现多少行。
  4. 【款式类特点】承受resizable,能够自界说输入框巨细。
  5. 【用户行为类特点】能够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的一切特点以外,还能够:

  1. 【值特点】处理change event里的checked,改为value
  2. 【值特点】常见多个binary field组合成一个selectable 组件,这儿值的处理需求契合selectable field的用法。
  3. 【辅佐类特点】label是指这个field的label,而binary的单个field也有它们自己的label,具体见下面各个field。传递binary label。

2-1. BaseRadio

单个Radio。一旦勾选无法撤销。

<BaseBinary type="radio" .../> ===> <BaseRadio .../>

承继以上BaseBinary的一切特点以外,还能够:

  1. 【值特点】回来值为boolean
  2. 【辅佐类特点】承受optionLabel,作为这一个选项的label。

2-2. BaseCheckbox

单个Checkbox。可勾选可撤销,还有一个中心态(依然放在binary里面,因为中心态是给treeSelect这种复合组件用的)。 单个Radio。一旦勾选无法撤销。

<BaseBinary type="checkbox" .../> ===> <BaseCheckbox .../>

承继以上BaseBinary的一切特点以外,还能够:

  1. 【值特点】承受ternary,当ternarytrue时,值有三种状况,用数字0,1,2表明。不然回来值为boolean
  2. 【辅佐类特点】承受optionLabel,作为这一个选项的label。

2-3. BaseSwitch

Switch。如下图:

封装表单元素的架构规划

<BaseBinary type="switch" .../> ===> <BaseSwitch .../>

承继以上BaseBinary的一切特点以外,还能够:

  1. 【值特点】回来值为boolean
  2. 【辅佐类特点】承受labelLeft,作为显现在左边的label。
  3. 【辅佐类特点】承受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的一切特点以外,还能够:

  1. 【值特点】单选的值为单个值,多选的值为一个数组。
  2. 【值特点】承受value,并核算出选项中与之平等的值,即selectedOption/selectedOptions
  3. 【值特点】承受allowValueOutOfValue,当这个特点为true时,value改动后有必要是选项中的一个,不然会被还原为上一次的值。考虑到后台或许会有脏数据,value在没做任何改动时仍是能够照本来的value显现。
  4. 【值特点】承受getDefaultValue(),这个办法决议了当某些依靠项(如某些其他field的值,选项)改动时,这个field默许改动value。
  5. 【值特点】承受isOptionEqualToValue(),用这个办法经过value挑选对应的option。
  6. 【选项类特点】选项类特点较为杂乱,请参阅这一篇文章:正在写。。。

3-1. BaseDropdown

带下拉框的挑选组件。

<BaseField type=“dropdown” multiple={true} .../> ==> <BaseSingleDropdown .../>
<BaseField type=“dropdown” multiple={false} .../> ==> <BaseMultiDropdown .../>

承继以上BaseSelectable的一切特点以外,还能够:

  1. 【功用】虚拟列表
  2. 【选项类特点】异步load options时,会有输入状况奉告用户。

3-1-1. BaseSingleDropdown

带下拉框的单选组件。

<BaseSingleDropdown .../>

承继以上BaseDropdown的一切特点以外,还能够:

  1. 【值特点】当clearabletrue时,选项中第一位会为一个带placeholder的空选项:
// options[0]
{
    label: '-- Select --',
    value: ''
}

这样用户挑选了某些值之后,还能够经过挑选这个值来清空。
2. 【值特点】承受defaultSelectFirst,当这个特点为true时,表明初始状况或选项更新后,默许挑选第一个选项。

3-1-2. BaseMultiDropdown

带下拉框的多选组件。

<BaseMultiDropdown .../>

承继以上BaseDropdown的一切特点以外,还能够:

  1. 【款式类特点】承受limitTags参数,界说在输入框里显现多少个选项。
  2. 【值特点】承受defaultSelectAll,意味着默许全选。

3-2. BaseAutocomplete

带下拉框和自动填充的挑选组件。

<BaseField type=“autocomplete” multiple={true} .../> ==> <BaseSingleAutocomplete .../>
<BaseField type=“autocomplete” multiple={false} .../> ==> <BaseMultiAutocomplete .../>

承继以上BaseSelectable的一切特点以外,还能够:

  1. 【值特点】当allowValueOutOfValuetrue时,用户能够自在输入。
  2. 【值特点】承受format,当用户能够自在输入时,假如这个组件值的类型较杂乱,能够经过这个办法得到契合格局要求的值。
  3. 【选项类特点】承受optionAddable,当用户自在输入了一个新值后,能够把这个新值加入到option list中(异步操作会发送恳求,同步操作会存到状况里)。
  4. 【选项类特点】异步load options时,会有输入状况奉告用户。既能够初始时一次性异步获取options,也能够跟着输入异步获取options。

3-2-1. BaseSingleAutocomplete

带下拉框和自动填充的单选组件。

<BaseSingleAutocomplete .../>

承继以上BaseAutocomplete的一切特点以外,还能够:

  1. 【值特点】承受clearable,当这个特点为true时,选项中第一位会为一个带placeholder的空选项:
// options[0]
{
    label: '-- Select --',
    value: ''
}

这样用户挑选了某些值之后,还能够经过挑选这个值来清空。
2. 【值特点】承受defaultSelectFirst,当这个特点为true时,表明初始状况或选项更新后,默许挑选第一个选项。

3-2-2. BaseMention

@功用,是由BaseSingleAutocomplete改换而成,type“@”后,跟着输入能够异步查询人名。一般常用在Textarea里。如下图:

封装表单元素的架构规划

<BaseMention .../>

承继以上BaseSingleAutocomplete的大部分特点以外,还能够:

  1. 【选项类特点】异步获取人员信息,像Jira一样。
  2. 【值特点】挑选好后,@后边其实仅仅可编辑可删除的文本。

3-2-3. BaseMultiAutocomplete

带下拉框和自动填充的多选组件。

<BaseMultiAutocomplete .../>

承继以上BaseAutocomplete的一切特点以外,还能够:

  1. 【款式类特点】承受limitTags参数,界说在输入框里显现多少个选项。
  2. 【值特点】承受defaultSelectAll,意味着默许全选。

3-3. BaseRadios

Radio组合的单选组件。

<BaseField type=“radios” .../> ==> <BaseRadios .../>

承继以上BaseSelectable的一切特点以外,还能够:

  1. 【选项类特点】承受’optionsDirection’,界说options的摆放方向,是横向仍是笔直,row仍是column

3-4. BaseCheckboxes

Checkbox组合的多选组件。

<BaseField type=“checkboxes” .../> ==> <BaseCheckboxes .../>

承继以上BaseSelectable的一切特点以外,还能够:

  1. 【选项类特点】承受’optionsDirection’,界说options的摆放方向,是横向仍是笔直,row仍是column

3-5. BaseTreeDropdown

下拉框是树组件的挑选组件。

<BaseField type=“tree” multiple={false} .../> ==> <BaseSingleTreeDropdown .../>
<BaseField type=“tree” multiple={true} .../> ==> <BaseMultiTreeDropdown .../>

承继以上BaseSelectable的一切特点以外,还能够:

  1. 【选项类特点】承受searchable,类似autocomplete组件,能够将带有关键字的节点挑选出来。
  2. 【选项类特点】父节点翻开时能够界说lazyload,异步获取子节点。

3-5-1. BaseTree

根底的树组件,独立存在,不在下拉框里。假如BaseTreeDropdown的searchablefalse,则选用这个组件。

<BaseSingleTreeDropdown searchable={false}.../> 封装 <BaseSearchTree .../>
<BaseMultiTreeDropdown searchable={false}.../> 封装 <BaseSearchTree .../>

树组件需求带有select功用,具体规划参阅这篇文章:正在写。。。

3-5-2. BaseSearchTree

带搜索功用的树组件,独立存在,不在下拉框里。将BaseTree与搜索框封装在了一同。假如BaseTreeDropdown的searchabletrue,则选用这个组件。

<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的一切特点以外,还能够:

  1. 【值特点】假如是已有值,需求用到BaseFileReview。
  2. 【值特点】界说file的值,需求区分文件本身和文件名。
  3. 【值特点】承受multiple,能够挑选单文件仍是多文件上传。
  4. 【校验类特点】承受accept,约束上传的文件类型。
  5. 【校验类特点】承受maxSize,约束上传的文件巨细。
  6. 【用户行为类特点】上传的办法,文件切片,是否能够中止或继续。
  7. 【款式类特点】上传过程中,是进度条仍是圆环。

4-1. BaseFileSelect

输入框式的文件挑选器。

<BaseFile type=“fileSelect” .../> ==> <BaseFileSelect .../>

承继以上BaseFile的一切特点

4-2. BaseFileArea

Drag & Drop式的文件上传。

<BaseFile type=“fileArea” .../> ==> <BaseFileArea .../>

承继以上BaseFile的一切特点以外,还能够:

  1. 【款式类特点】承受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的一切特点以外,还能够:

  1. 【值特点】承受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,这样做的优点如下:

  1. 这样的组件现已将值核算和校验等操作封装在其中了,开发者运用起来会十分轻松。
  2. 有利于做集成测验。
  3. 有利于写开发文档。
  4. 给未来假如需求将组件做成动态组件做准备。

总结

咱们开发的要点并不是在组件本身,事实上,我计划直接用现有的组件库,由于需求通用不同的组件库,每个组件库对应的接口不同,因此需求特制Adaptor,比方在咱们的框架中格局化办法叫“format”,而某个组件库的同样功用的办法名叫“formatter”,另一个组件库这个办法名叫“formateValue”,这样Adaptor的重要性就在于此,仅仅仅仅经过改换姓名,将不同的组件库接入进来,这种办法也是coding浪费最少的办法了。
具体Adaptor的规划这在写。。。 接下来,是FreeForm和FormArray的封装:正在写。。。