资讯专栏INFORMATION COLUMN

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

IntMain / 1069人阅读

摘要:嗯,可能也是最后一版。。。用例用法接受一个参数。和上面的作用一样,相同的会覆盖中的值写在的事件中。或者,会在提交的时候调用,形参为中的数据,和一样。参考上面的例子获取所有的数据获取所有改变过的数据

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

简化版的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 = {};
      }
      
      componentWillReceiveProps(nextProps){
          if(this.props.initialValues != nextProps.initialValues) {
              this.initialValues = { ...initialValues, ...nextProps.initialValues };
              this.resetForm();
          }
      }

      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 ;
      }
    }

    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 (
      
{ this.instance=instance; }} initialValues={{ name: true }}/>
) } }
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 (
      
        
        
        
      
    )
  }
}

用法:

@reactForm(options)

options: {
  fields: ["field1", "field2", "field3", "checkbox"...], // names of fields
  initialValues: { "field1":"value1", "field2":"value2", "checkbox":true }, // the initial values of fields
  validate: fn, // the function will be called when onChange
  validateOnBlur: fn, // the function will be called when onBlur
  withRef: false // when this is true, you can get the inner component by using getInstance
}

Component 接受一个initialValues参数。和上面的initialValues作用一样,相同的key会覆盖option.initialValues中的值

API

handleSubmit, 写在formonSubmit事件中。

onSubmit={handleSumit}或者onSubmit={handleSubmit(fn)}fn会在form提交的时候调用,形参为form中的数据

fields,和redux-form一样。参考上面的例子

getValues 获取所有的数据

getTouchedValues 获取所有改变过(onChange)的数据

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82589.html

相关文章

  • CentOS 生产环境配置

    摘要:最新的已经释出,更新了,非常赞。不过目前尚未释出,等待中。初始配置对于一般配置来说,不需要安装仓库,本文主要在于希望跟随的配置流程,紧跟红帽公司对于服务器的配置说明。 原文来自静雅斋,转载请注明出处。 生产环境和开发环境测试环境都不一样,所以配置都不能随意,对于大多数情况来说,RHEL 绝对是一个最佳选择,除了最稳定的内核发布和最全的驱动支持,还能享受到 RHEL 10 年生命周期中 ...

    daydream 评论0 收藏0
  • 精彩文章赏析 - 收藏集 - 掘金

    摘要:掘金原文地址译文出自掘金翻译计划译者请持续关注中文维护链接获取最新内容。由于以下的浏览器市场份额已逐年下降,所以对于浏览器技巧三视觉效果前端掘金揭秘学习笔记系列,记录和分享各种实用技巧,共同进步。 沉浸式学 Git - 前端 - 掘金目录 设置 再谈设置 创建项目 检查状态 做更改 暂存更改 暂存与提交 提交更改 更改而非文件 历史 别名 获得旧版本 给版本打标签 撤销本地更改... ...

    godiscoder 评论0 收藏0
  • Python发布自己的模块到Pypi

    摘要:学习我们已经感受到他的强大之处,内置模块和强大的第三方模块,省去了我们重复造轮子的过程,谁没有一颗想造轮子的心,今天来发布一个自己的轮子先解释下是官方的第三方库的仓库,所有人都可以下载第三方库或上传自己开发的库到。 学习Python我们已经感受到他的强大之处,内置模块和强大的第三方模块,省去了我们重复造轮子的过程,but 谁没有一颗想造轮子的心,今天来发布一个自己的轮子 先解释下PyP...

    zsy888 评论0 收藏0
  • React造轮子:拖拽排序组件「Dragact」

    摘要:造轮子的一些思考首先,我们的需求是用户能够方便的调整后台的各种表盘位置。内的所有组件必须不能重叠,还要能自动排序某些组件要可以设定静态的,也就是固定在那里,不被布局的任何变动而影响。为了快速获得这种心态的转变,你要做的就是造轮子。 先来一张图看看: showImg(https://segmentfault.com/img/remote/1460000013305417?w=600&h=...

    Charlie_Jade 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<