赞
踩
1. 假如是登录页面,包含姓名和密码,新建Login.jsx
import React from 'react'; import Form from './Form'; export default class Login extends React.Component{ constructor() { super(); this.state = { Form : { model : { name : '', password : '', }, rules : { name : {require :true,message:'请输入姓名'}, password : {require :true , min : 6,message:'请输入密码'}, }, } }; this.formRef = null; } submit =()=> { const model = this.formRef.getFormData(); const validateResult = this.formRef.validate(); // console.log('model' , model) //这里可以根据form的抛出验证方法验证填写字段 }; render() { return ( <Form onRef={ref=>this.formRef=ref} className={'form'} model={this.state.Form.model} rules={this.state.Form.rules}> <Form.Item rule={{require :true,message:'请输入姓名5555'}} name={'name'} label="姓名" isItem={true}> <input type="text" style={{marginLeft : "20px"}} placeholder="请输入姓名"/> </Form.Item> <Form.Item name={"password"} label="密码" isItem={true}> <input type="password" placeholder="请输入密码"/> </Form.Item> <div> <button type="button" onClick={this.submit}>提交</button> </div> </Form> ); } }
2. 写Form组件,新建Form.jsx
/** *为了实现数据绑定,感觉Form.Item里面的内容,在这里是完全拦截,用 const children = this.props.children; const Elements = []; //formItem里面的内容 React.Children.map(children, (child, i) => { const name = child.type.name ? child.type.name.toLowerCase() :child.type.toLowerCase(); Elements.push({ name : name, props : child.props }) }); */ import React from 'react'; import styles from './Form.module.less'; import FormItem from "./FormItem"; import {deepClone} from '../../../util' let thizForm; //等于class Form,可以在static Item里面调用功能了 class Form extends React.Component{ constructor(props) { super(props); const state = { model: {}, rules: {}, validateErrors : {}, }; for(let name in props.model){ state.validateErrors[name] = false; } this.state = state; this.ref = React.createRef(); thizForm = this; } validate =()=> { //验证功能 const model = this.props.model; const rules = this.props.rules; let validateErrors = deepClone(this.state.validateErrors); for(let name in validateErrors){ validateErrors[name] = true; if(rules[name].require){ } } this.setState({ validateErrors : validateErrors, }); }; componentWillMount(){ //传递ref到父级页面 if(this.props.onRef){ this.props.onRef(this) } //把props里面的数据,绑定到Form-class -> state里面,未做深拷贝,懒得写了 const props = deepClone( this.props); const rules = props.rules; //formItem可能有自己的rule React.Children.map(props.children, (child,i) => { const childProps = child.props; if(childProps.hasOwnProperty('rule')){ rules[childProps.name] = childProps.rule; } }); this.setState({ rules : rules, model: props.model, }); } getFormData(){ return this.state.model; } render() { //拦截Form里面的内容,在这里做传入Form.props的参数进去,为了实现数据绑定 let newChildrens = []; React.Children.map(this.props.children, (child,i) => { let newChild = child; if(child.props.isItem){ newChild = React.cloneElement(newChild, { showValidateError : this.state.validateErrors[child.props.name] || false,//是否展示每个信息下边的提示信息 model : this.props.model, ...child.props, rule : this.state.rules[child.props.name], }); } newChildrens.push( <React.Fragment key={i}>{newChild}</React.Fragment> ); }); if(newChildrens.length === 1){ newChildrens = newChildrens[0] } return ( <form className={styles.form}> {/*{this.props.children}*/} {newChildrens} </form> ); } //Form.Item的组件方法 static Item = class extends React.Component { constructor(props) { super(props); this.state = { showValidateError : false, }; } onChange =(name , value)=>{ //只是写了input的对应方法 const model = thizForm.state.model; model[name] = value; thizForm.setState({ model : model }); }; static getDerivedStateFromProps(props, state) { if (props.showValidateError !== state.showValidateError) { let { showValidateError } = props; return { showValidateError, //把父组件最新的props.type重新赋值到 子组件state.type }; } // 父组件的值没有变化,这里不做任何操作。 return null; } render() { const children = this.props.children; const Elements = []; //里面的表单 //拦截children,传入Form-props给的name字段,onChange的时候,能根据name对应的修改Form->state->model->[name]的值 React.Children.map(children, (child, i) => { const name = child.type.name || child.type; Elements.push({ name : name.toLowerCase(), props : child.props }) }); return ( <FormItem {...this.props} showValidateError={this.state.showValidateError}> { Elements.map((Item , index) => { return <div key={index}> <Item.name {...Item.props} key={index} onChange={e => this.onChange(this.props.name , e.target.value)}/> { this.state.showValidateError ? <p className={styles.errorMessage}>{this.props.rule.message}</p> : null } </div> }) } </FormItem> ); } }; } export default Form;
3. 编写FormItem组件,新建FormItem.jsx
import React from 'react'; import styles from './Form.module.less' export default class FormItem extends React.Component{ constructor(props) { super(props); this.state = { showValidateError : props.showValidateError, }; } // componentDidUpdate(prevProps, prevState, snapshot) { // console.log('prevProps' , prevProps) // } render() { return ( <label htmlFor={this.props.key} className={styles.formItemContent}> <span className={'label'}>{this.props.label}:</span> {this.props.children} </label> ); } }
- 查看结果
输入的时候,查看Form.state,已经录入了。
验证功能
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。