首先我们自定义一个Form组件,该组件用于包裹所有需要包裹的表单组件,通过contex向子组件暴露两个属性:
- model:当前Form管控的所有数据,由表单name和value组成,如{name:'ConardLi',pwd:'123'}。model可由外部传入,也可自行管控。
- changeModel:改变model中某个name的值。
- class Form extends Component {
- static childContextTypes = {
- model: PropTypes.object,
- changeModel: PropTypes.func
- }
- constructor(props, context) {
- super(props, context);
- this.state = {
- model: props.model || {}
- };
- }
- componentWillReceiveProps(nextProps) {
- if (nextProps.model) {
- this.setState({
- model: nextProps.model
- })
- }
- }
- changeModel = (name, value) => {
- this.setState({
- model: { ...this.state.model, [name]: value }
- })
- }
- getChildContext() {
- return {
- changeModel: this.changeModel,
- model: this.props.model || this.state.model
- };
- }
- onSubmit = () => {
- console.log(this.state.model);
- }
- render() {
- return <div>
- {this.props.children}
- <button onClick={this.onSubmit}>提交</button>
- </div>
- }
- }
下面定义用于双向绑定的HOC,其代理了表单的onChange属性和value属性:
- 发生onChange事件时调用上层Form的changeModel方法来改变context中的model。
- 在渲染时将value改为从context中取出的值。
- function proxyHoc(WrappedComponent) {
- return class extends Component {
- static contextTypes = {
- model: PropTypes.object,
- changeModel: PropTypes.func
- }
- onChange = (event) => {
- const { changeModel } = this.context;
- const { onChange } = this.props;
- const { v_model } = this.props;
- changeModel(v_model, event.target.value);
- if(typeof onChange === 'function'){onChange(event);}
- }
- render() {
- const { model } = this.context;
- const { v_model } = this.props;
- return <WrappedComponent
- {...this.props}
- value={model[v_model]}
- onChange={this.onChange}
- />;
- }
- }
- }
- @proxyHoc
- class Input extends Component {
- render() {
- return <input {...this.props}></input>
- }
- }
(编辑:ASP站长网)
|