redux-flow-form v1.0.4
redux-flow-form
use json schema to generate form. Based on react and redux.
背景
表单开发在企业级应用中是业务中最常见的需求,但是每次开发表单,都如鲠在喉,如芒刺背,显而易见有几个常见痛点:
- 表单开发流程相似,表单开发周期长,没有高效的多人协同开发方案,维护成本高。
- 表单项逻辑代码分散,不易复用。
- 表单开发涉及文件模块多,bug不易定位。
如果能有一个多人协同开发表单的方案,不仅能够提高代码的复用性,而且能够显著的提升表单的研发效率。
设计思路
1. 表单开发流程
我们首先来考虑在业务中,我们开发表单的时候,究竟在做一件什么事情?
- 处理表单中的交互逻辑:在表单结合redux的使用场景下,表单项输入数据需要触发dispatch改变对应reducer,在整体store的改变下,需要重新渲染页面
- 处理表单中数据的提交逻辑:提交之前需要进行表单整体校验,校验通过之后发送提交请求,请求成功或失败之后执行相应的回调方法
2. 核心思路
为什么要提效表单?倘若一个系统只有一个表单,那就没有提效的必要性了。就是因为在企业级应用的系统中,表单的出现频率高,所以才有了各种表单的提效方案。 然而现有的解决方案无法满足我们在开发中的痛点,我们的痛点是什么?开发的慢吗?不是的,纵观整个企业级应用的平台,痛点一定是没有规范导致的,没有规范会导致一系列问题,例如:不同开发方式下的表单维护成本高,组件无法实现复用,无法快速定位bug等等。如果能够定出一套合理的规范,那么必然会有针对规范的落地解决方案,这样的话,就可以提升整体的开发效率。 所以,我们给出的表单解决方案本质上就是定义一种开发规范,并提供了落地的解决方案让这套开发规范能够显著提高表单开发效率。这套开发规范的落地对于开发者来说就是一套简单且完备的表单schema。 开发同学只需要完善这份schema就可以完成表单的开发了。
2.1 schema
表单schema 规定了两点,form和items:
form: 业务逻辑写在哪里。 对业务逻辑的规定保证了表单渲染和具体业务的解耦。
items:使用什么组件进行渲染。 从规范上鼓励大家沉淀公共的表单项组件,在一个成熟的系统中,表单项的交互一定是趋于收敛的。如果大家持续的沉淀表单项,后续表单基本没有表单项的开发成本,可以显著减少开发工作量。
我们沉淀的核心逻辑就是保证上面的两点解决方案能够切实落地,保证在整个系统中只有一种开发表单的规范,而且通过持续不断的沉淀表单项可以有效的降低后续开发表单的时间。
2.2 redux在表单中的作用
为了提高复用性,表单项都是独立开发的,独立开发表单项带来的一个问题就是表单和表单项的通信问题。使用redux 管理双方通信的数据value 和errorMsg。这样表单和表单项的开发就彻底解耦了。
这就是redux-flow-form 全部的设计思路!
适用场景
所有使用redux+react框架的企业级应用系统
使用方式
1. 安装
npm install --save-dev redux-flow-form
2. 开发适用于redux-flow-form的表单组件(以antd组件库为例)
输入组件Input
import React from 'react';
import {get} from 'lodash';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {actionUtils, formUtils} from 'redux-flow-form';
import {Input} from 'antd';
const onFieldChangeCreator = actionUtils.onFieldChangeCreator;
const getActionPrefix = formUtils.getActionPrefix;
const mapStateToProps = (state, ownProps) => {
const {
formProps,
compProps
} = ownProps;
const {field} = compProps; // 通过formConfig配置获取对应表单项字段名
const {formName, statePath} = formProps;
const value = get(state, `${statePath}.${formName}.${field}`, ''); // 普通组件直接通过store路径获取对应值;表单项组件通过formConfig配置信息获取store中对应的字段值
return {
value
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
const {compProps, actions, formProps} = ownProps;
const {field} = compProps;
const {formName, bizName} = formProps;
const prefix = getActionPrefix(bizName, formName);
const onFieldChange = onFieldChangeCreator(prefix);
return bindActionCreators(
{
onChange: e => dispatch => {
dispatch(onFieldChange({
key: field,
value: e.value
}));
}
},
dispatch
);
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(props => <Input value={props.value} onChange={props.onChange} />);
提交组件Button
import React from 'react';
import {connect} from 'react-redux';
import {Button} from 'antd';
import {bindActionCreators} from 'redux';
const mapStateToProps = (state, ownProps) => {
const text = ownProps.compProps.text;
return {
text
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
const {actions} = ownProps;
return bindActionCreators(
{
onClick: () => (dispatch, getState) => {
actions.operate(dispatch, getState);
}
},
dispatch
);
};
export default connect(mapStateToProps, mapDispatchToProps)(
props => <Button onClick={props.onClick}>{props.text}</Button>
);
3. formConfig初始化
import {tools, config} from 'redux-flow-form';
import Button from './button';
import Input from './input';
const getFormInfo = tools.formInfoUtils.getFormInfo;
const bizName = 'reduxFlowForm';
const statePath = 'example';
const formName = 'example';
export default {
form: {
props: {
bizName,
statePath,
formName
},
operations: {
items: [
{
usingComp: {
props: {
text: '提交'
},
Comp: Button
},
actions: {
operate: (dispatch, getState) => {
const params = getFormInfo({state: getState(), statePath, formName});
console.log(params);
}
}
}
]
}
},
items: [
{
layoutType: config.FORM_ITEM_LAYOUT_TYPE.GRID_ITEM,
usingComp: {
props: {
field: 'title',
defaultValue: ''
},
Comp: Input
}
}
]
};
4. 生成表单实体挂载在业务中
import React, {useContext} from 'react';
import {ReactReduxContext} from 'react-redux';
import FormGenerator from 'redux-flow-form';
import formConfig from './formConfig';
export default () => {
const instance = FormGenerator.getInstance(useContext(ReactReduxContext).store);
const Form = instance.createForm();
return <Form {...formConfig} />;
}
5. 生成reducer挂载在store中
import {tools} from 'redux-flow-form';
import formConfig from './formConfig';
const formReducerFactory = tools.formReducer;
export default formReducerFactory(formConfig)
启动项目
npm run start 之后,就能看到example数据节点已经在store中,编辑表单数据同步更新。
测试
# 下载依赖
npm i
# 启动测试
npm run test
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago