
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@amazebird/schme-form
Advanced tools
表单是后台管理最常遇到的一种数据管理模式,在管理系统中被大量使用,但是在react中,表单的开发却相对比较复杂,需要绑定数据源, 需要去写大量的模版代码来定义每一个Field内容,包括不同的应用场景:新增,修改,查看,以及表单之间存在复杂的关联操作,联动规则,造成表单开发的工作量较大, 影响项目的开发效率。复杂的业务关联也容易使代码间的耦合关系复杂,造成可读性差与难以维护性。 表单组件提供一种相对简易的方式来开发对应的表单功能,通过配置化的方式简化表单开发。使用
表单组件提供的功能包括:
- 表单组件提供了:新增,修改,查看三种模式,只需设置参数
mode
,不需要再进行额外处理- 界面布局:表单组件提供了一套标准的界面布局,但如果需要个性化,表单组件自身也提供了默认展现模式
shema 是表单组件的配置项,通过对shema的配置,可以动态生成对应的表单,配置的内容为表单中包含哪些字段,每个字段的验证规则等内容
const schema = {
"userName":{
label:'用户名',
placeholder:'请填写用户名',
component:'input',
disabled:false,
visible:false,
keepAlive:true,
options: [],
rules:{
required:[true,'请填写用户名称'], // 是否必填
pattern:^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$ //正则
max:50, // 最大长度/数量
min:10, // 最小长度/数量
validator: ({ value, formData })=>{ // 自定义验证方法,用于处理业务化的验证规则, 如果 required, max, min, pattern 不能满足验证需求时,可以自定义validator
const {startTime,endTime} = formData
if(startTime > endTime) return '开始时间不能大于结束时间'
},
...
},
observer:{
watch:'firstName',
action: (firstName)=>{
return {value:`${newValue}=1111`}
}
},
props:{
className:'user-name'
}
},
"firstName":{
label:'姓氏',
component:'input'
...
}
]
SchemaForm是表单引擎的主组件,SchemaForm将根据定义好的schema
自动生成对应的表单
属性 | 说明 | 可选参数 | 默认 |
---|---|---|---|
schema | 表单配置 | -- | -- |
data | 表单实体对象,用于初始化表单数据 | -- | |
mode | 表单模式 | add(新增)/modify(修改)/detail(详情) | add |
trigger | 将组件的props/state注册为trigger,在schema中可以通过observer来监听trigger的变动,实现与props/state的联动 | -- | -- |
属性 | 说明 | 类型 | 默认 | 支持初始化 | 支持联动 |
---|---|---|---|---|---|
label | 用于在表单上显示的字段名 | string | react element | -- | -- | -- |
component | 表单字段所使用的组件, 支持string 和component 两种类型,string 为当前表单引擎提供的内置的field组件 类型,例如:'input' ,同时也支持component 为用户自定义组件(详见“自定义表单组件”) | string | component | -- | -- | -- |
placeholder | 占位文本,与input等组件配合使用 | string | -- | -- | -- |
disabled | 是否禁用操作 | boolean | function | object | false | true | true |
visible | 是否显示当前字段 | boolean | function | object | true | true | true |
value | 设置当前字段的值 value不支持直接赋值,只支持初始化方法和监听 但要注意避免产生循环监听,循环监听可能产生死循环 例如:A监听b,c监听a,b监听c,这时当b值改变时,可能造成死循环 | function | object | -- | true | true |
keepAlive | 当字段处于不可见状态时,是否保持field的value。将keepAlive设置为false时,当字段不可见时,该字段的value将会丢失 | boolean | true | -- | -- |
options | 适用于选择相关组件的可选项处理 ,例如:select, radio,picker, cascader 等 | array | function | object | [] | true | true |
format | 如果你需要对表单的输入(input),输出值(output)进行格式化的话,可以使用format input 仅支持function output 支持function 和false output 为false 时,会从formdata中删除该feild ,当一个field 主要的作用只是参与表单联动与交互的中间值,并不需要提交时,可以使用该方式input 和output 只在数据初始化与表单onSubmit时才会处理 | {input:[function(value)],output:[function(value)| false ]} | -- | -- | -- |
defaultValue | 默认值 | any | -- | -- | -- |
rules | 字段验证,支持rc-form中的所有验证类型,但简化了设置方式: | function | object | true | true | true |
name | 用于给rules 提供默认的错误提示语,以简化rules的配置例如:当 name 为用户名 ,只设置了{required:true} 时,其对应的默认错误提示为请填写用户名 。如果设置了 label 时,name 会默认取label 的值作为自身的值 | string | -- | -- | -- |
type | 如果表单字段存在层级结构时,父级字段需要设置type 类型是对象object 还是数组array ,SchemaForm会根据父字段类型对其子字段进行相应处理 | string ("object" | "array") | -- | -- | -- |
fields | 如果表单字段存在层级结构时,fields 用于配置对应的子字段 | object | -- | -- | -- |
field | 层级结构中存一种特殊情况,数组字段下的item并不是一个对象,而是一个基础类型,这个时需要配置field 以便进行区分 | object | -- | -- | -- |
observer | observer 属性用于字段连动,当其他的联动字段无法满足业务需求时,observer 提供最强大的联动能力,除了key,component等特殊属性以外,几乎能够修改任意属性 | {watch:[array],action:[function]} | -- | -- | -- |
props | props 的属性都会直接透传给对应的 field 组件,以满足不同组件的个性化属性需要 | object | {} | true | true |
初始化:field的某个属性可能并不是一开始就明确的,可能需要通过调用接口来确定它的值,这时可以使用初始化方法来动态对属性进行赋值,初始化方法支持异步,但初始化方法仅在表单初始化时执行一次。
监听:表单中很多场景下需要字段间的联动,这时可以使用监听方式对field的属性进行赋值
示例:
const schema = {
"courseType":{
label:"课程类型",
component:"select",
...
},
"studentType":{
label:"学生类型",
...
},
"course":{
label:"课程",
component:"select",
options:async ({formData})=>{ // 根据课程类型对课程进行初始化
const courseItems = await request.get('/courses',{courseType:formData.courseType})
},
visible:{
watch:["studentType"],
action:(studentType)=>{
return studentType === 1 // 当学生类型为1时,才显示课程
}
}
}
}
在很多场景下,添加页、修改页、详情页,在布局上,字段上,是十分类似的,仅存在一些小的差异,例如在修改页中某些字段不能修改,在详情页中,字段都是以文本的形式展现等。在这样的场景下,通过mode,我们只需要针对不同模式的差异点对每个字段进行配置,就可以便捷地实现添加,修改,详情这三个功能。
默认情况下,内置组件会根据mode选择合适的展示组件。
如果默认方式无法满足你的需求,还可以选择通过观察模式observer
来根据实际业务情况,自定义要展现的组件。
如果是自定义组件,那就需要开发者自己在组件中,根据mode
来自行处理组件的展现。
当然,你也可以将观察模式与自定义组件结合起来使用。
示例:
有时候,字段的变动可能不完全通过表单的值产生联动,而依赖于业务组件中的属性或者内部状态,这时我们就需要用到trigger,trigger可以使SchemaForm的字段可以监听到组件中的属性或状态。
当该trigger属性发生变动时,就可以触发对应的action方法,改变field的形态。对于trigger的监听在watch
的声明时需要以"*
"作为前缀,以表示当前监听的是trigger
,因此为了避免产生不可预期的错误,请注意不要将字段的key值以"*
"作为前缀.
个性化布局模式支持对表单布局的自定义,包括可以增加一些卡片,对字段位置的设定,增加一些装饰元素等
export default class FormDemo extends Component {
render() {
return (
<SchemaForm schema={schema} data={data} mode={FORM_MODE.MODIFY}>
<FormCard title="基础信息" > // FormCard 是表单卡片容器
<Item field="userName" /> // 通过FormItem 设置当前位置要展现的表单字段, fields定义要显示的字段
<Item field='password' />
<Item field='realName' />
<Item field='phone' />
<Item field='phoneList' />
</FormCard>
<Row> // 也可以随意表单的布局结构与字段位置
<Item field='area' {...this.props} />
</Row>
</SchemaForm>
)
}
}
表单组件中内置了许多其于antd的内置组件,内置组件是在antd组件的基础上,增加了Form.Item绑定,以及form.getFieldDecorator的包装 当前支持的组件有(持续增加中):
组件 | 说明 |
---|---|
input | 输入框 |
DatePicker | 日期选择器 |
TimePicker | 时间选择器 |
Radio | 单选框 |
Select | 下拉选择框 |
TextArea | 文本框 |
除了上面表单引擎内置的组件外,表单引擎还提供对自定义组件的支持,以满足不同业务场景的需要。 表单引擎会把所有相关属性与方法传递组自定义组件,主要属性与方法有:
属性/方法 | 说明 |
---|---|
form | 表单对象 |
mode | 当前表单模式 |
field | 当前字段配置 |
value | 当前字段值 |
onChange | 当修改了字段值时,通过调用onchange方法将最新的字段值提交给表单,在onChange方法中将自动调用validator对字段值进行校验 |
其他属性与方法 |
export default class PhoneList extends React.Component {
render () {
const { value, onChange } = this.props
const _add = () =>{
onChange([...value, '111111111'])
}
const _decrease = () =>{
const newValue = [...value]
newValue.pop()
onChange(newValue)
}
return (
<div>
<div>{
value && value.map(phone => <div>{phone}</div>)
}
</div>
<Button onClick={_add}>添加</Button>
<Button onClick={_decrease}>减少</Button>
</div>
)
}
}
嵌套字段是表单中比较复杂的情况,例如表单某个字段是一个对象,对象中的每个属性需要单独渲染, 再例如表单某个字段是一个数组,数组中可能是对象,也可能是string。也可能对象中嵌套数组,数组中又嵌套对象……==! 总的来说,嵌套字段存在两种型式:对象字段,数组字段
属性/方法 | 类型 | 默认值 | 说明 |
---|---|---|---|
label | string | 按钮显示文本 | |
onClick | function(formData,form ) | 如果设置了validate, 则需要通过验证才会触发onClick方法 | |
validate | boolean/array[fieldnames] | false | 是否需要验证 为true时,表单会先对formData进行验证,验证通过了才会触发onClick方法 |
onError | function(errors) | 只有设置了validate,onError才会生效 | |
debounce | boolean/number | false | 设置按钮的节流 -boolean:debounce为true时,将默认为500ms -number:当debounce为number时,将会以debounce的value将会作为节流时长 |
visible | function(formData,mode) | 返回false则隐藏该按钮,返回true则显示 | |
reset | boolean | false | 设置了reset后,点击按钮会重置表单 |
render | component | 自定义Button | |
... | 其他属性与 Button 组件属性一致,如果设置了render,则需要开发者自行处理 |
表单中的数组与其他单一字段不同,数组字段是需要循环遍历渲染。
action(changeValue,{})
不建议在多个observer中对同一个属性进行修改,因为observer的执行顺利并不确定。
value的联动是相对比较复杂的问题,由于通过父节点也能更改子节点的value值,所以就存在多处对同一个field的value进行修改的可能性。 为了避免造成逻辑上的不确定性,请确保只存在一处对value的的联动修改。
### 与UForm比较 UForm采用了rxjs实现事件分发,事件的指向性更强,有更强的针对性,以提升渲染性能,减少不必要的组件渲染。 UForm的问题:
FAQs
Unknown package
The npm package @amazebird/schme-form receives a total of 1 weekly downloads. As such, @amazebird/schme-form popularity was classified as not popular.
We found that @amazebird/schme-form demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.