小编典典

ReactJS两个组件进行通信

javascript

我刚开始使用ReactJS,但对我遇到的问题有些困惑。

我的应用程序本质上是一个带有过滤器的列表和一个用于更改布局的按钮。目前我使用的三个组成部分:<list />< Filters/><TopBar />,现在很明显,当我更改设置,在< Filters />我想引起一些方法<list />来更新我的看法。

如何使这三个组件相互交互,或者我需要可以对其进行更改的某种全局数据模型?


阅读 305

收藏
2020-04-25

共1个答案

小编典典

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

  1. <Filters /> 是的子组件 <List />
  2. 这两个<Filters /><List />是一个父组件的孩子
  3. <Filters /><List />完全位于单独的根组件中。

可能还有其他我没有想到的情况。如果您的不适合这些,请告诉我。以下是一些有关如何处理前两种情况的非常粗糙的示例:

场景1

您可以将处理程序从传递<List /><Filters />,然后可以在onChange事件上调用该处理函数以使用当前值过滤列表。

#1的JSFiddle→

/** @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);

场景2

与方案#1类似,但父组件将是将处理函数传给的组件<Filters />,并将过滤后的列表传递给<List />。我更喜欢这种方法,因为它使<List />脱离了<Filters />

#2的JSFiddle→

/** @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);

2020-04-25