React + Flux - 将带有输入的嵌套组件绑定到单个 "model"

React + Flux - Binding nested components with inputs to a single "model"

来自 Angular,理解作用域以及 directives/controllers 与 HTML 的交互方式与我正在尝试做的这个简单示例相比似乎相当合乎逻辑。

基本上,我有几个组件。

/** @jsx React.DOM */
var React = require('react');
var {TextInput} = require("./controls/TextInput.jsx");

var Group = React.createClass({
    render: function () {      
        console.log(this.props.formdata); // passed from parent
        return (
                 <fieldset className="">
                    <legend>My Field Group</legend>
                     {this.props.field.fields.map(function(fld, i) {                           
                     return (<div className="my-field">
                                <TextInput formdata={formdata} field={fld} />
                            </div>);
                 })}
             </fieldset>
        );
    }
});

exports.Group = Group;

我的 TextInput 看起来像这样:

** @jsx React.DOM */
var React = require('react');

var TextInput = React.createClass({
    render: function () {

       return (
         <div className="form-group">
           <label htmlFor={this._reactInternalInstance._rootNodeID+'_input'}>{this.props.field.label}</label>
           <input type="" className="form-control" id={this._reactInternalInstance._rootNodeID+'_input'} value={???} placeholder=""/>
         </div>
        );
    }
});

exports.TextInput = TextInput;

首先,我很确定我对 _rootNodeId 的处理可能会更好,但还没有找到更好的例子。

我的主要问题是弄清楚如何将文本框的值绑定到我的模型。

我也是"using" Flux,并且有一个

var SomeStore = require('../stores/some-store');

var SomeActions = require('../actions/some-action');

我可以用来管理数据和调度事件的对象。本质上,我需要做的是,当其中一个子文本输入的值发生变化时,我想处理该变化,可能会更改模型中的其他一些值,并告诉受影响的 controls/dom 元素自行更新。

欢迎任何建议。

谢谢 山姆

我假设您想在不提交实际提交输入的情况下执行此操作。在 React/Flux,商店是您最接近 "model" 的地方。您将需要构建您的 Flux 架构,以便您的 React 组件监听对商店的更改。例如,在您的 TextInput 组件中,我假设您不想实际提交数据(只是在您输入后立即更新信息):

** @jsx React.DOM */
var React = require('react');
var SomeActions = require('../actions/some-action');

var TextInput = React.createClass({

    handleChange: function () {
        var generatedRef = this._reactInternalInstance._rootNodeID+'_input';
        var data = React.findDOMNode(this.refs[generatedRef]).value;
        SomeActions.UpdateStore(data);
    },

    render: function () {
        var generatedRef = this._reactInternalInstance._rootNodeID+'_input';

        return (
            <div className="form-group">
                <label htmlFor={this._reactInternalInstance._rootNodeID+'_input'}>{this.props.field.label}</label>
                <input type="text" ref={generatedRef} onChange={this.handleChange} className="form-control" id={this._reactInternalInstance._rootNodeID+'_input'} placeholder=""/>
            </div>
        );
    }
});

exports.TextInput = TextInput;

声明 generatedRef 不是必需的,但我这样做是为了清楚起见。在 SomeActions 中,您将需要通过调度程序调度有效负载。 SomeStore 需要侦听该类型的有效负载并相应地更新其数据,然后发出其他组件正在侦听的更改。例如:

/** @jsx React.DOM */
var React = require('react');
var {TextInput} = require("./controls/TextInput.jsx");
var SomeStore = require('../stores/some-store');


var getData = function () {
    return SomeStore.retrieveData(); //should return an object 
};

var Group = React.createClass({
    onChange: {
    this.setState(getData());
    },

    componentDidMount: {
        SomeStore.addChangeListener(this.onChange);
    },

    componentWillUnmount: {
        SomeStore.removeChangeListener(this.onChange);
    },
    render: function () {      
        console.log(this.props.formdata); // passed from parent
        return (
            <fieldset className="">
                <legend>My Field Group</legend>
                 {this.props.field.fields.map(function(fld, i) {                           
                 return (
                     <div className="my-field">
                         <TextInput formdata={formdata} field={fld} />
                     </div>);
                })}
            </fieldset>
        );
    }
});

exports.Group = Group;

这是我在不知道你的行为和商店是什么样子的情况下所能做的最好的。基本上,只要您更改输入字段中的数据,handleChange 就会发送一个操作。此操作将更新商店。商店应该在更新时发出 change 事件。任何侦听这些更改的组件都将相应更新以反映商店的当前数据。