中後臺領域中,數據錄入是一個重要的場景,在該場景中form(表單)扮演一個重要的角色。表單中涉及到大量的交互,主要表如今如下幾個方面:javascript
咱們從一個簡單登陸頁的例子提及,來總結form是如何使用的。html
咱們直接使用react的受控組件模式,對每一個輸入項的狀態保存在組件state中,經過onChange事件,實時更新值。java
import React from 'react';
class FormDemo extends React.Component {
state = {
username: '',
password: '',
usernameMsg: '',
passwordMsg: '',
};
onChangeName = e => {
const value = e.target.value;
this.setState({
username: value,
usernameMsg: !value ? '請填寫' : ‘’, // 非空校驗
});
};
onChangePassword = e => {
const value = e.target.value;
this.setState({
password: value,
passwordMsg: !value ? '請填寫' : ‘', // 非空校驗
});
};
handleSubmit = () => {
// post data
};
render() {
// 獲取數據和錯誤信息
const { username, password, usernameMsg, passwordMsg } = this.state;
return (
<form>
<input value={username} onChange={this.onChangeName} />
<span>{usernameMsg}</span>
<input value={password} onChange={this.onChangePassword} />
<span>{passwordMsg}</span>
<button type="submit" onClick={this.handleSubmit}>提交</button>
</form>
);
}
}
複製代碼
這種方法百分之百使用原生的方式實現:表單的每個field都對應於組件內的state的一個值,每個field有一個對應的錯誤信息用於展現錯誤,每一個field的值經過onChange事件進行改變。這種方式實現簡單明瞭,可是當field較多時,須要大量的重複這種value + onChange
的模式。因此,須要一種方式,將重複的工做抽象出來。react
rc-form內部使用fieldsStore對全部field進行集中式管理,當數據改變時,重繪整個form。json
import { createForm } from 'rc-form';
class Form extends React.Component {
submit = () => {
this.props.form.validateFields((error, value) => {
console.log(error, value);
});
}
render() {
let usernameErrors, passwordErrors;
const { getFieldProps, getFieldError } = this.props.form;
return (
<div>
<input {...getFieldProps('username', {rules: [{required: true}]})}/>
{(usernameErrors = getFieldError('password')) ? errors.join(',') : null}
<input {...getFieldProps('password', {rules: [{required: true}]})}/>
{(passwordErrors = getFieldError('password')) ? errors.join(',') : null}
<button onClick={this.submit}>submit</button>
</div>
);
}
}
export createForm()(Form);
複製代碼
createForm()
使用高階組件的方式,對form注入了一些額外的方法與屬性。getFieldProps
方法用於把field註冊到fieldsStore裏面,fieldsStore對field的變化進行追蹤。能夠看出相比第一種方式,rc-form把狀態與UI進行分層,咱們省去了對每個field的狀態管理,不用再去爲每個field進行狀態進行value + onChange
的重複。antd
在以上過程當中,咱們完成了登陸的功能邏輯,可是還缺乏表單的樣式。表單樣式包括兩部分:表單的總體樣式和每一個field的樣式。因而咱們抽象出Form和FormItem用於承載樣式,因而就有了antdForm。antd form就是在rc-form的基礎上增長了form佈局演化而來。咱們也能夠經過自定義Form和FormItem + rc-form的形式去實現form的佈局。架構
代碼以下:app
<Form onSubmit={(values) => { submit(values) }}>
<Form.Item label="姓名">
{getFieldDecorator('name')(<Input />)}
</Form.Item>
<Form.Item label="密碼">
{getFieldDecorator('password')(<Input.Password />)}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">提交</Button>
</Form.Item>
</Form>
複製代碼
antd-form的架構以下: 異步
在使用antd-form過程當中,遇到如下問題:分佈式
uform很好的解決了使用form過程當中遇到的各類問題,以uform 0.4.x版本爲例(1.x版本發生了很大的變化)。
UForm 主要分爲三層結構:
uform採用分佈式狀態管理,數據同步靠根組件廣播須要更新子組件重繪,根組件只負責消息分發。這樣能夠作到只更新單個組件。uform支持json schema和集中性的反作用管理。
使用uform代碼以下:
const Schema = {
user: {
type: 'object',
properties: {
username: {
type: 'string',
title: '用戶名',
required: true,
},
password: {
type: 'string',
title: '密碼',
required: true,
},
}
}
const defaultValue = {
user: {
username: '',
password: ''
}
}
<SchemaForm
labelCol={8}
wrapperCol={16}
schema={Schema}
defaultValue={defaultValue}
onSubmit={this.onSubmit}
>
</SchemaForm>
複製代碼
使用uform,咱們能夠先定義form的schema和默認值,以後交給uform進行渲染。 uform能夠方便的處理多種場景,如聯動等。