【问题标题】:ReactJS complex hierarchy and component form submissionReactJS 复杂层次结构和组件表单提交
【发布时间】:2015-11-21 02:58:24
【问题描述】:

我有一个很大的表格,里面有 4 个部分。

看起来像这样:

  _______________
  |      |      |
  |  1   |  2   |
  |______|______|
  |      |      |
  |  3   |  4   |
  |______|______|

所有部分形成自己的 jsx 文件。第 1 节称为 Section1.jsx,第 2 节称为 Section2.jsx,依此类推。

第 1 部分基本上是联系信息,您填写您的姓名、公司、地址等。非常简单。

第 2 部分与第 1 部分基本相同,但它是一个可供您选择的选项列表。您在第 2 节中所做的更改,在第 4 节中更改了某种形式的控件。例如,如果我有一个下拉菜单显示“使用公制而不是英语转换”,那么第 4 节将有不同的单位。

第 3 节很简单,第 4 节是一个网格。

现在,我的所有组件都已启动并运行,但现在我无法找到一种方法来查看我的 react 组件的所有状态,并将数据冒泡给父母,然后再提交表单.

所以这是我所说的层次结构:

  • ReactJS 根节点
    • ReactJS Section1 节点
      • 呈现:5 个 html 输入框
    • ReactJS Section2 节点
      • ReactJS dropdown1 节点
        • 渲染:选择下拉菜单(在 componentDidMount 上使用 select2.js)
      • ReactJS dropdown2 节点
        • 渲染:选择下拉菜单(在 componentDidMount 上使用 select2.js)
      • ReactJS dropdown3 节点
        • 渲染:选择下拉菜单(在 componentDidMount 上使用 select2.js)
      • ReactJS dropdown4 节点
        • 渲染:选择下拉菜单(在 componentDidMount 上使用 select2.js)
    • ReactJS Section3 节点
      • ReactJS dropdown1 节点
        • 渲染:选择下拉菜单(在 componentDidMount 上使用 select2.js)
    • ReactJS Section4 节点
      • 渲染:表并创建用于本地存储的行(在 componentDidMount 上使用 datatables.js)

我有一个提交按钮。我需要浏览不同文件中的所有这些部分,才能在此表单上提交所有收集的数据,但我很难找到最好的方法。

ReactJS 似乎在父子关系或子父子关系方面表现出色。但是,父母到孩子到孙子,或者孙子到孩子到父母到祖父母,这变得更难了。这似乎是疯狂的维护,特别是如果我想在这些部分之一中添加更新的嵌套组件。有没有一种方法可以让我在每个反应节点上附加某种机制,注册数据的这些状态,并允许提交按钮知道这种机制并随时提交?

我应该为此研究 Flux 吗?我有点开始了,但我发现自己认为将它添加到我的项目中会使事情变得比它需要的更复杂,我发现自己在兔子洞里走得更远。

或者我是否需要添加 AngularJS 之类的东西并将侦听器附加到我的所有字段?我见过AngularJS和ReactJS一起使用的项目,reactjs只用于渲染。

我碰巧读了这篇文章: http://ctheu.com/2015/02/12/how-to-communicate-between-react-components/

解释 3 种关系:

  1. 所有者到所有者(父母到孩子)
  2. 所有者到所有者(子到父)
  3. 它们不相关

对于第三个选项(这是我真正想了解的更多内容),他提到使用名为 PubSub(发布/订阅)的第 3 方库,这里有一个 javascript 库:

https://github.com/mroderick/PubSubJS

但我真的不确定这是否是最好的方法。

【问题讨论】:

  • Flux 可能会很好,这样您就不必管理顶级组件中的所有状态。
  • 我一直在阅读有关 Flux 的更多信息,但对我来说似乎太多了。它在很大程度上依赖 Nodejs 作为他们所有教程的要求,所以这让我相信它与你使用的那种 Web 服务器高度耦合。 ReactJS 是一个不干扰的库,Flux 似乎肯定会干扰我所拥有的。
  • Flux 只是您构建 React 代码的一种方式,它绝对不与服务器耦合。我认为您应该使用 Flux,在您的特定情况下,您将拥有一个 FormStore 来保持所有部分的状态,以及一个顶部控制器将部分数据作为道具传递。当您点击“提交”按钮时,您无事可做,因为您的表单的当前状态(即用户输入的结果)已经保存在您的 FormStore 中。
  • 正如其他人所提到的,我也强烈建议您进入 Flux。到最后,您将能够轻松地在一个地方管理应用程序状态。
  • 例如,下拉菜单的更改事件触发Action,它调用Dispatcher,然后在Store 中听到,您将在其中保存状态。您的主应用程序 JS 文件与 Store 挂钩,因此每当 Store 发生变化时,它可以从 Store 获取所需的数据并使用 props 传递给子(和孙子)组件,即数据流动在一个方向。我发现 this article 是 Fl​​ux 的一个非常好的起点。

标签: reactjs


【解决方案1】:

我只是继续添加 PubSubJS,如原始帖子中所述。我非常感谢 ctheu 详细展示了这种解决方案,并感谢 mroderick 创建 PubSub 库。

https://github.com/mroderick/PubSubJS

这是一个非常棒的库,我可以订阅我的所有组件,以便在它们挂载时监听特定的令牌,这使它们能够“监听”发布的任何类型的更改。

这样做的好处是,您可以随时订阅您的组件,并且只要有内容发布,订阅的组件就会运行它们的功能。

这就是我的意思:

// create a function to subscribe to topics
var mySubscriber = function( msg, data ){
    console.log( msg, data );
};

var token = PubSub.subscribe( 'demo', mySubscriber );

到目前为止,控制台没有打印任何内容:

var demoClick = React.createClass({
    getInitialState: function() {
        return {value: 'Hello!'};
    },
    handleChange: function(event) {
        this.setState({value: event.target.value})
        PubSub.publish('demo', event.target.value)
    },
    render: function() {
        var value = this.state.value;
        return (<input type="text" value={value} onChange={this.handleChange} /> );

}});

只要我更改文本框中的值,我的控制台日志就会被触发

现在我拿订阅码:

var token = PubSub.subscribe( 'demo', mySubscriber );

并且放在我的react组件之后,当我修改输入框的时候还是会触发的。

我什至可以更进一步,将这段代码添加到组件生命周期中:componentWillMount 和 componentWillUnmount。

所以在 componentWillMount 中,我可以订阅,在 componentWillUnmount 中,我可以取消订阅令牌。

If 感觉有点像它是一个全局事件系统,但实际上它是由 PubSub 管理的。

【讨论】:

    【解决方案2】:

    你可以给你的子表单组件(它们都在父 HTML 中定义了 refs)一个 val() 函数,这样你就可以使用这些 refs 从父表单组件调用它。您的所有数据都会冒泡到父级,但您不需要将其保存在父级的状态中。

    如果您需要将高级事件传递给子组件,您可以通过将道具传递给您的子组件来轻松完成此操作。

    【讨论】:

    • 我之前确实走过这条路,但这似乎是一种非常迂回的做事方式。我真的很想使用直接功能。因此,在下面的回答中,我使用了 pubsub,并创建了一个名为“subscribes”的库,因此它包含所有订阅,以及指示发布来自何处的评论。当我添加一个新的模型绑定框架时,​​它工作得非常好。您提供的解决方案同样有效,但不是我喜欢的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多