IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    React-Simple-Form轮子第一版释出

    Clark发表于 2017-04-20 17:30:55
    love 0

    嗯,可能也是最后一版。。。哈哈~~~只是写着玩

    简化版的redux-form,只是觉得不需要redux-form那么复杂的功能,也不想要和redux关联,而且希望有一个简单管理form的东西,所以就写了一个。肯定有很多不足,比如checkbox/radio group怎么管理。。。没有解决。。。

    import React from 'react';
    
    export default function reactForm(options){
      const { fields=[], initialValues={}, validate, validateOnBlur, withRef } = options;
    
      return (Component)=>{
        class Form extends React.Component {
          constructor(props) {
            super(props);
    
            this.initialValues = { ...initialValues, ...props.initialValues };
            this.state = this.getInitialFields();
    
            this.touchedKeys = {};
          }
    
          getInitialFields = ()=>{
            return fields.reduce((prev, key)=>{
              prev[key] = typeof this.initialValues[key] == "undefined" ? undefined : this.initialValues[key];
              return prev;
            }, {})
          }
    
          resetForm = ()=>{
            this.setState(this.getInitialFields());
          }
    
          setInstance = (instance)=>{
            this.instance = instance;
          }
    
          getInstance = ()=>{
            if(withRef) return this.instance;
            console.error("Can not get instance when withRef is false");
          }
    
          getValues = ()=>{
            return fields.reduce((prev, key)=>{
              prev[key] = this.state[key];
              return prev;
            }, {});
          }
    
          getTouchedValues = ()=>{
            let result = {};
            for(let key in this.touchedKeys) {
              if(this.touchedKeys.hasOwnProperty(key)){
                result[key] = this.state[key];
              }
            }
            return result;
          }
    
          onFieldChange = (e, key)=>{
            let value = ['radio', 'checkbox'].includes(e.target.type) ? e.target.checked : e.target.value;
    
            console.log(`trigger field change with ${key} ${value}`);
    
            this.setState({
              [key]: value
            }, ()=>{
              this.touchedKeys[key] = true;
            });
            validate && validate(key, value);
          }
    
          onFieldBlur = (e, key)=>{
            let value = ['radio', 'checkbox'].includes(e.target.type) ? e.target.checked : e.target.value;
    
            validateOnBlur(key, value);
          }
    
          handleSubmit = (fn)=>{
            if(typeof fn == "function") {
              return (e)=>{
                e.preventDefault();
                e.stopPropagation();
                fn(this.getValues());
              }
            } else {
              fn.preventDefault();
              fn.stopPropagation();
            }
          }
    
          buildFields = ()=>{
            return fields.reduce((prev, key)=>{
              let value = this.state[key];
              let field = { onChange: (e)=>{ this.onFieldChange(e, key) } };
              
              if(typeof value === "boolean") field.checked = value;
              else field.value = value;
    
              if(validateOnBlur) field.onBlur = (e)=>{ this.onFieldBlur(e, key) };
    
              prev[key] = field;
              return prev;
            }, {})
          }
    
          buildProps = (props)=>{
            let _props = { ...props };
    
            _props.fields = this.buildFields();
            _props.handleSubmit = this.handleSubmit;
            _props.getValues = this.getValues;
            _props.getTouchedValues = this.getTouchedValues;
            _props.resetForm = this.resetForm;
    
            if(withRef) {
              _props.ref = this.setInstance;
            }
    
            return _props;
          }
    
          render(){
            let props = this.buildProps(this.props);
    
            return <Component { ...props } />;
          }
        }
    
        return Form;
      }
    } 

    用例:

    index.js

    import React from 'react';
    import Form from './form';
    
    export default class FormApp extends React.Component {
      constructor(props) {
        super(props);
      }
    
      onClick = ()=>{
        console.log(this.instance.getTouchedValues());
      }
    
      render(){
        return (
          <div>
            <Form ref={instance=>{ this.instance=instance; }} initialValues={{ name: true }}/>
            <button style={{ marginLeft: "200px" }} onClick={this.onClick}>Values</button>
          </div>
        )
      }
    }

    form.js

    import React from 'react';
    import reactForm from 'components/react-form';
    
    function validate(key, value){
      console.log(`validateOnBlur ${key} ${value}`);
    }
    
    @reactForm({ fields: ['name', 'bbb'], withRef: true, initialValues: { bbb: "bbbbbb" }, validateOnBlur: validate })
    export default class Form extends React.Component {
      constructor(props) {
        super(props);
      }
    
      onSubmit = (values)=>{
        console.log(values);
    
        let { getTouchedValues } = this.props;
        console.log(getTouchedValues());
    
        this.props.resetForm();
      }
    
      render(){
        let { fields: { name, bbb }, handleSubmit } = this.props;
    
        return (
          <form onSubmit={handleSubmit(this.onSubmit)} style={{ marginLeft: "200px" }}>
            <label>
              name:
              <input type="checkbox" name="name" value="123" {...name}/>
            </label>
            <label>
              bbb
              <input type="text" name="bbb" {...bbb}/>
            </label>
            <button type="submit">submit</button>
          </form>
        )
      }
    }


沪ICP备19023445号-2号
友情链接