ReactJS 两个组件通信 [英] ReactJS Two components communicating

查看:31
本文介绍了ReactJS 两个组件通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始使用 ReactJS,但我遇到了一个问题.

我的应用程序本质上是一个带有过滤器的列表和一个用于更改布局的按钮.目前我正在使用三个组件:<list/>, <过滤器/>,现在很明显,当我在 中更改设置时过滤器/> 我想在 中触发一些方法来更新我的视图.

我怎样才能让这 3 个组件相互交互,或者我是否需要某种全局数据模型来进行更改?

解决方案

最佳方法取决于您计划如何安排这些组件.现在想到的几个示例场景:

  1. 的子组件
  2. 都是父组件的子组件
  3. 完全位于单独的根组件中.

可能还有其他我没有想到的场景.如果您的不适合这些,请告诉我.下面是一些非常粗略的例子,说明我是如何处理前两种情况的:

场景 #1

您可以将处理程序从 <List/> 传递给 ,然后可以在 onChange 上调用它code> 事件以使用当前值过滤列表.

#1 的 JSFiddle →

/** @jsx React.DOM */var 过滤器 = React.createClass({句柄过滤器更改:函数(){var value = this.refs.filterInput.getDOMNode().value;this.props.updateFilter(value);},渲染:函数(){return ;}});var List = React.createClass({getInitialState:函数(){返回 {listItems: ['芝加哥', '纽约', '东京', '伦敦', '旧金山', '阿姆斯特丹', '香港'],名称过滤器:''};},处理过滤器更新:函数(过滤器值){this.setState({名称过滤器:过滤器值});},渲染:函数(){var displayItems = this.state.listItems.filter(function(item) {var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());返回(匹配!== -1);}.bind(this));var 内容;如果(displayedItems.length > 0){var items = displayItems.map(function(item) {返回 
  • {item}
  • ;});content = <ul>{items}</ul>} 别的 {content = <p>没有匹配这个过滤器的项目</p>;}返回 (<div><过滤器 updateFilter={this.handleFilterUpdate}/><h4>结果</h4>{内容}

    );}});React.renderComponent(, document.body);


    场景 #2

    类似于场景#1,但父组件会将处理函数传递给<Filters/>,并将过滤后的列表传递给<List/>.我更喜欢这种方法,因为它使 分离.

    #2 的 JSFiddle →

    /** @jsx React.DOM */var 过滤器 = React.createClass({句柄过滤器更改:函数(){var value = this.refs.filterInput.getDOMNode().value;this.props.updateFilter(value);},渲染:函数(){return ;}});var List = React.createClass({渲染:函数(){var 内容;如果(this.props.items.length > 0){var items = this.props.items.map(function(item) {返回 
  • {item}
  • ;});content = <ul>{items}</ul>} 别的 {content = <p>没有匹配这个过滤器的项目</p>;}返回 (<div className="results"><h4>结果</h4>{内容}

    );}});var ListContainer = React.createClass({getInitialState:函数(){返回 {listItems: ['芝加哥', '纽约', '东京', '伦敦', '旧金山', '阿姆斯特丹', '香港'],名称过滤器:''};},处理过滤器更新:函数(过滤器值){this.setState({名称过滤器:过滤器值});},渲染:函数(){var displayItems = this.state.listItems.filter(function(item) {var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());返回(匹配!== -1);}.bind(this));返回 (<div><过滤器 updateFilter={this.handleFilterUpdate}/><List items={displayedItems}/>

    );}});React.renderComponent(, document.body);


    场景 #3

    当组件无法在任何类型的父子关系之间通信时,文档建议设置全局事件系统.

    I just got started with ReactJS and am a little stuck on a problem that I have.

    My application is essentially a list with filters and a button to change the layout. At the moment I'm using three components: <list />, < Filters /> and <TopBar />, now obviously when I change settings in < Filters /> I want to trigger some method in <list /> to update my view.

    How can I make those 3 components interact with each other, or do I need some sort of global data model where I can just make changes to?

    解决方案

    The best approach would depend on how you plan to arrange those components. A few example scenarios that come to mind right now:

    1. <Filters /> is a child component of <List />
    2. Both <Filters /> and <List /> are children of a parent component
    3. <Filters /> and <List /> live in separate root components entirely.

    There may be other scenarios that I'm not thinking of. If yours doesn't fit within these, then let me know. Here are some very rough examples of how I've been handling the first two scenarios:

    Scenario #1

    You could pass a handler from <List /> to <Filters />, which could then be called on the onChange event to filter the list with the current value.

    JSFiddle for #1 →

    /** @jsx React.DOM */
    
    var Filters = React.createClass({
      handleFilterChange: function() {
        var value = this.refs.filterInput.getDOMNode().value;
        this.props.updateFilter(value);
      },
      render: function() {
        return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />;
      }
    });
    
    var List = React.createClass({
      getInitialState: function() {
        return {
          listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'],
          nameFilter: ''
        };
      },
      handleFilterUpdate: function(filterValue) {
        this.setState({
          nameFilter: filterValue
        });
      },
      render: function() {
        var displayedItems = this.state.listItems.filter(function(item) {
          var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());
          return (match !== -1);
        }.bind(this));
    
        var content;
        if (displayedItems.length > 0) {
          var items = displayedItems.map(function(item) {
            return <li>{item}</li>;
          });
          content = <ul>{items}</ul>
        } else {
          content = <p>No items matching this filter</p>;
        }
    
        return (
          <div>
            <Filters updateFilter={this.handleFilterUpdate} />
            <h4>Results</h4>
            {content}
          </div>
        );
      }
    });
    
    React.renderComponent(<List />, document.body);
    


    Scenario #2

    Similar to scenario #1, but the parent component will be the one passing down the handler function to <Filters />, and will pass the filtered list to <List />. I like this method better since it decouples the <List /> from the <Filters />.

    JSFiddle for #2 →

    /** @jsx React.DOM */
    
    var Filters = React.createClass({
      handleFilterChange: function() {
        var value = this.refs.filterInput.getDOMNode().value;
        this.props.updateFilter(value);
      },
      render: function() {
        return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />;
      }
    });
    
    var List = React.createClass({
      render: function() {
        var content;
        if (this.props.items.length > 0) {
          var items = this.props.items.map(function(item) {
            return <li>{item}</li>;
          });
          content = <ul>{items}</ul>
        } else {
          content = <p>No items matching this filter</p>;
        }
        return (
          <div className="results">
            <h4>Results</h4>
            {content}
          </div>
        );
      }
    });
    
    var ListContainer = React.createClass({
      getInitialState: function() {
        return {
          listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'],
          nameFilter: ''
        };
      },
      handleFilterUpdate: function(filterValue) {
        this.setState({
          nameFilter: filterValue
        });
      },
      render: function() {
        var displayedItems = this.state.listItems.filter(function(item) {
          var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());
          return (match !== -1);
        }.bind(this));
    
        return (
          <div>
            <Filters updateFilter={this.handleFilterUpdate} />
            <List items={displayedItems} />
          </div>
        );
      }
    });
    
    React.renderComponent(<ListContainer />, document.body);
    


    Scenario #3

    When the components can't communicate between any sort of parent-child relationship, the documentation recommends setting up a global event system.

    这篇关于ReactJS 两个组件通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆