實(shí)現(xiàn)高階組件版表單組件

高階組件版表單組件設(shè)計(jì)思路進(jìn)階

表單組件要求實(shí)現(xiàn)數(shù)據(jù)收集辛辨、校驗(yàn)、提交等特性旁蔼,可通過(guò)高階組件擴(kuò)展

高階組件給表單組件傳遞一個(gè)input組件包裝函數(shù)接管其輸入事件并統(tǒng)一管理表單數(shù)據(jù)

高階組件給表單組件傳遞一個(gè)校驗(yàn)函數(shù)使其具備數(shù)據(jù)校驗(yàn)功能

Input.js文件內(nèi)容如下:

import React, { Component } from 'react'

const Input = (props) => {

? ? return <input {...props} />

}

export default class CustomizeInput extends Component {

? ? constructor(props) {

? ? ? ? super(props);

? ? }

? ? render() {

? ? ? ? const { value = "", ...otherProps } = this.props;

? ? ? ? return (

? ? ? ? ? ? <div style={{padding: '10px'}}>

? ? ? ? ? ? ? ? <Input style={{outline: 'none'}} value={value} {...otherProps} />

? ? ? ? ? ? </div>

? ? ? ? )

? ? }

}

1.實(shí)現(xiàn)一個(gè)簡(jiǎn)單的表單功能:

MyRCForm.js文件內(nèi)容如下:

import React, { Component } from 'react'

import Input from '../components/Input';

class MyRCForm extends Component {

? ? constructor(props) {

? ? ? ? super(props);

? ? ? ? this.state = {

? ? ? ? ? ? username: "",

? ? ? ? ? ? password: ""

? ? ? ? }

? ? }

? ? nameChange = (e) => {

? ? ? ? this.setState({

? ? ? ? ? ? username: e.target.value

? ? ? ? })

? ? }

? ? passwordChange = (e) => {

? ? ? ? this.setState({

? ? ? ? ? ? password: e.target.value

? ? ? ? })

? ? }

? ? submit = () => {

? ? ? ? const { username, password } = this.state;

? ? ? ? console.log("syta", username, password); // sy-log

? ? }

? ? render() {

? ? ? ? const { username, password } = this.state;

? ? ? ? return (

? ? ? ? ? ? <div>

? ? ? ? ? ? ? ? <h3>MyRCForm</h3>

? ? ? ? ? ? ? ? <Input

? ? ? ? ? ? ? ? ? ? placeholder="Username"

? ? ? ? ? ? ? ? ? ? value={username}

? ? ? ? ? ? ? ? ? ? onChange={this.nameChange}

? ? ? ? ? ? ? ? />

? ? ? ? ? ? ? ? <Input

? ? ? ? ? ? ? ? ? ? placeholder="Password"

? ? ? ? ? ? ? ? ? ? value={password}

? ? ? ? ? ? ? ? ? ? onChange={this.passwordChange}

? ? ? ? ? ? ? ? />

? ? ? ? ? ? ? ? <button onClick={this.submit}>submit</button>

? ? ? ? ? ? </div>

? ? ? ? )

? ? }

}

export default MyRCForm

2.使用rc-form的高階組件createForm:

MyRCForm.js文件內(nèi)容如下:

import React, { Component } from 'react'

import Input from '../components/Input';

import { createForm } from 'rc-form'; // 安裝rc-form:npm install rc-form

const nameRules = {required: true, message: "請(qǐng)輸入姓名袜瞬!"};

const passwordRules = {required: true, message: "請(qǐng)輸入密碼!"};

@createForm()

class MyRCForm extends Component {

? ? constructor(props) {

? ? ? ? super(props);

? ? }

? ? componentDidMount() {

? ? ? ? const { setFieldsValue } = this.props.form;

? ? ? ? setFieldsValue({

? ? ? ? ? ? username: "default"

? ? ? ? });

? ? }

? ? submit = () => {

? ? ? ? const { getFieldsValue, getFieldValue } = this.props.form;

? ? ? ? console.log("syta", getFieldsValue(), getFieldValue("username")); // sy-log

? ? }

? ? render() {

? ? ? ? console.log("props", this.props);

? ? ? ? const { getFieldDecorator } = this.props.form;


? ? ? ? return (

? ? ? ? ? ? <div>

? ? ? ? ? ? ? ? <h3>MyRCForm</h3>

? ? ? ? ? ? ? ? {getFieldDecorator("username", {rules: [nameRules]})(<Input

? ? ? ? ? ? ? ? ? ? placeholder="Username"

? ? ? ? ? ? ? ? />)}

? ? ? ? ? ? ? ? {getFieldDecorator("password", {rules: [passwordRules]})(<Input

? ? ? ? ? ? ? ? ? ? placeholder="Password"

? ? ? ? ? ? ? ? />)}? ? ?

? ? ? ? ? ? ? ? <button onClick={this.submit}>submit</button>

? ? ? ? ? ? </div>

? ? ? ? )

? ? }

}

export default MyRCForm

打印結(jié)果如下:

3.自定義一個(gè)高階組件createForm:

MyRCForm.js文件內(nèi)容如下:

import React, { Component } from 'react';

import Input from '../components/Input';

import { createForm } from '../components/my-rc-form/index';

const nameRules = {required: true, message: "請(qǐng)輸入姓名制圈!"};

const passwordRules = {required: true, message: "請(qǐng)輸入密碼!"};

@createForm

class MyRCForm extends Component {

? ? constructor(props) {

? ? ? ? super(props);

? ? }

? ? componentDidMount() {

? ? ? ? const { setFieldsValue } = this.props.form;

? ? ? ? setFieldsValue({

? ? ? ? ? ? username: "李明",

? ? ? ? ? ? password: "123"

? ? ? ? });

? ? }

? ? submit = () => {

? ? ? ? const { getFieldsValue, getFieldValue, validateFields } = this.props.form;

? ? ? ? console.log("syta", getFieldsValue(), getFieldValue("username")); // sy-log

? ? ? ? validateFields((err, vals) => {

? ? ? ? ? ? if(err) {

? ? ? ? ? ? ? ? console.log("失敗", err)

? ? ? ? ? ? }else {

? ? ? ? ? ? ? ? console.log("成功", vals)

? ? ? ? ? ? }

? ? ? ? })

? ? }

? ? render() {

? ? ? ? console.log("props", this.props);

? ? ? ? const { getFieldDecorator } = this.props.form;

? ? ? ? return (

? ? ? ? ? ? <div>

? ? ? ? ? ? ? ? <h3>MyRCForm</h3>

? ? ? ? ? ? ? ? {getFieldDecorator("username", {rules: [nameRules]})(<Input

? ? ? ? ? ? ? ? ? ? placeholder="Username"

? ? ? ? ? ? ? ? />)}

? ? ? ? ? ? ? ? {getFieldDecorator("password", {rules: [passwordRules]})(<Input

? ? ? ? ? ? ? ? ? ? placeholder="Password"

? ? ? ? ? ? ? ? />)}

? ? ? ? ? ? ? ? <button onClick={this.submit}>submit</button>

? ? ? ? ? ? </div>

? ? ? ? )

? ? }

}

export default MyRCForm

components/my-rc-form/index.js文件內(nèi)容如下:

import React, { Component } from 'react'

export function createForm(Cmp) {

? ? return class extends Component {

? ? ? ? constructor(props) {

? ? ? ? ? ? super(props);

? ? ? ? ? ? this.state = {}

? ? ? ? ? ? this.options = {}

? ? ? ? }

? ? ? ? getFieldsValue = () => {

? ? ? ? ? ? return {...this.state};

? ? ? ? }

? ? ? ? getFieldValue = (name) => {

? ? ? ? ? ? return this.state[name];

? ? ? ? }

? ? ? ? setFieldsValue = (newStore) => {

? ? ? ? ? ? this.setState(newStore)

? ? ? ? }

? ? ? ? handleChange = (e) => {

? ? ? ? ? ? const { name, value } = e.target;

? ? ? ? ? ? this.setState({

? ? ? ? ? ? ? ? [name]: value

? ? ? ? ? ? }, () => {

? ? ? ? ? ? ? ? console.log("state", this.state);

? ? ? ? ? ? })

? ? ? ? }

? ? ? ? getFieldDecorator = (fieldName, option) => InputCmp => {

? ? ? ? ? ? this.options[fieldName] = option;

? ? ? ? ? ? return React.cloneElement(InputCmp, {

? ? ? ? ? ? ? ? name: fieldName,

? ? ? ? ? ? ? ? value: this.state[fieldName] || "",

? ? ? ? ? ? ? ? onChange: this.handleChange

? ? ? ? ? ? });

? ? ? ? }

? ? ? ? validateFields = (callback) => {

? ? ? ? ? ? let err = [];

? ? ? ? ? ? for(let fieldName in this.options) {

? ? ? ? ? ? ? ? if(!this.state[fieldName]) {

? ? ? ? ? ? ? ? ? ? err.push({

? ? ? ? ? ? ? ? ? ? ? ? [fieldName]: "err"

? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if(err.length === 0) {

? ? ? ? ? ? ? ? callback(null, {...this.state});

? ? ? ? ? ? }else {

? ? ? ? ? ? ? ? callback(err, {...this.state});

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? getForm = () => {

? ? ? ? ? ? return {

? ? ? ? ? ? ? ? getFieldsValue: this.getFieldsValue,

? ? ? ? ? ? ? ? getFieldValue: this.getFieldValue,

? ? ? ? ? ? ? ? setFieldsValue: this.setFieldsValue,

? ? ? ? ? ? ? ? getFieldDecorator: this.getFieldDecorator,

? ? ? ? ? ? ? ? validateFields: this.validateFields

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? render() {

? ? ? ? ? ? const form = this.getForm();

? ? ? ? ? ? return (

? ? ? ? ? ? ? ? <div>

? ? ? ? ? ? ? ? ? ? <Cmp {...this.props} form={form}/>

? ? ? ? ? ? ? ? </div>

? ? ? ? ? ? )

? ? ? ? }

? ? }

}

打印結(jié)果如下:

注意:antd3 的設(shè)計(jì)有個(gè)問(wèn)題畔况,就是局部變化會(huì)引起整體變化鲸鹦,即每次輸入框的值發(fā)生變化的時(shí)候,會(huì)重新渲染頁(yè)面跷跪,比較消耗性能馋嗜,不過(guò) antd4 改進(jìn)了這個(gè)問(wèn)題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末域庇,一起剝皮案震驚了整個(gè)濱河市嵌戈,隨后出現(xiàn)的幾起案子覆积,更是在濱河造成了極大的恐慌听皿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宽档,死亡現(xiàn)場(chǎng)離奇詭異尉姨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吗冤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門又厉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)九府,“玉大人,你說(shuō)我怎么就攤上這事覆致≈堆” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵煌妈,是天一觀的道長(zhǎng)儡羔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)璧诵,這世上最難降的妖魔是什么汰蜘? 我笑而不...
    開(kāi)封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮之宿,結(jié)果婚禮上族操,老公的妹妹穿的比我還像新娘。我一直安慰自己比被,他們只是感情好色难,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著姐赡,像睡著了一般莱预。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上项滑,一...
    開(kāi)封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天依沮,我揣著相機(jī)與錄音,去河邊找鬼枪狂。 笑死危喉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的州疾。 我是一名探鬼主播辜限,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼严蓖!你這毒婦竟也來(lái)了薄嫡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颗胡,失蹤者是張志新(化名)和其女友劉穎毫深,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體毒姨,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哑蔫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闸迷。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嵌纲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腥沽,到底是詐尸還是另有隱情逮走,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布今阳,位于F島的核電站言沐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酣栈。R本人自食惡果不足惜险胰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望矿筝。 院中可真熱鬧起便,春花似錦、人聲如沸窖维。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铸史。三九已至鼻疮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琳轿,已是汗流浹背判沟。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崭篡,地道東北人挪哄。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像琉闪,于是被迫代替她去往敵國(guó)和親迹炼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容