React 组件通信,父子传值、跨组件传值、兄弟组件传值

一、父传子

父组件:

class App extends Component {
  render() {
    return (
      <div>
        {/* 类组件 */}
        <Child name="李四" age={26} hobbies={['睡觉']} />
        {/* 类组件默认值 */}
        <Child />
        {/* 函数组件 */}
        <Child2 />
      </div>
    )
  }
}

类子组件:

class Child extends Component {
  render() {
    const { name, age, hobbies } = this.props;
    return (
      <div>
        <h3>{`姓名:${name},年龄:${age}`}</h3>
        <h3>爱好:</h3>
        <ul>
          {
            hobbies.map(item => {
              return <li key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

函数子组件:

function Child2(props) {
  const { name, age, hobbies } = props;
  return (
    <div>
      <h3>{`姓名:${name},年龄:${age}`}</h3>
      <h3>爱好:</h3>
      <ul>
        {
          hobbies.map(item => {
            return <li key={item}>{item}</li>
          })
        }
      </ul>
    </div>
  )
}

类子组件中设置默认值及类型检查:

class Child extends Component {
  // 类型检查
  static propTypes = {
    // isRequired 必传
    name: PropTypes.string.isRequired,
    age: PropTypes.number,
    hobbies: PropTypes.array
  }
  // 设置默认值
  static defaultProps = {
    name: "小明",
    age: 18,
    hobbies: ['吃饭', '睡觉', '打豆豆']
  }
  render() {
    const { name, age, hobbies } = this.props;
    return (
      <div>
        <h3>{`姓名:${name},年龄:${age}`}</h3>
        <h3>爱好:</h3>
        <ul>
          {
            hobbies.map(item => {
              return <li key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

函数组件和类组件通用设置默认值及类型检查:

// 类型检查
Child2.propTypes = {
  // isRequired 必传
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  hobbies: PropTypes.array
}
// 设置默认值
Child2.defaultProps = {
  name: "小明",
  age: 18,
  hobbies: ['吃饭', '睡觉', '打豆豆']
}

二、子传父

父组件:

class App extends Component {
  constructor() {
    super();
    this.state = {
      data: []
    }
  }
  render() {
    return (
      <div>
        <Child getData={this.handleGetData} />
        <h2>列表:</h2>
        <ul>
          {
            this.state.data.map(item => {
              return <li key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
  // 定义箭头函数接收子组件传过来的值
  handleGetData = (data) => {
    this.setState({
      data
    })
  }
}

子组件:

class Child extends Component {
  constructor() {
    super();
    this.state = {
      // 子组件初始值
      data: ['a', 'b', 'c']
    }
  }
  render() {
    const { getData } = this.props;
    return (
      // 将子组件的值传递到父组件
      <button onClick={e => getData(this.state.data)}>获取数据</button>
    )
  }
}

三、跨组件通信(context)

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

父组件:

// 创建 Context 并设置默认值
const listContext = React.createContext([111, 222, 333])

// 父组件
class App extends Component {
  constructor() {
    super();
    this.state = {
      list: ['aaa', 'bbb', 'ccc']
    }
  }
  render() {
    return (
      <div>
        <div>我是父组件</div>
        {/* 调用 Provider 组件发送数据 */}
        <listContext.Provider value={this.state}>
          <Child />
        </listContext.Provider>
      </div>
    )
  }
}

子组件:

class Child extends Component {
  render() {
    return (
      <div>
        <div>我是子组件</div>
        <GrandSon />
      </div>
    )
  }
}

孙子组件(类):

class GrandSon extends Component {
  // 接收 Context
  static contextType = listContext;
  constructor() {
    super();
    this.state = {};
  }
  render() {
    return (
      <div>
        <div>我是孙子组件</div>
        <ul>
          {
            this.context.list.map(item => {
              return <li key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
}
  • 通过类组件里定义 static contextType 接收父组件传递过来的 Context 值。**
// 接收父组件传递过来的 Context 值
static contextType = listContext;
  • 通过组件名调用 ContextType 接收父组件传递过来的 Context 值。
// 通过类名接收父组件传递过来的 Context 值
GrandSon.contextType = listContext;

孙子组件(函数):

function GrandSon() {
  return (
    <div>
      <div>我是孙子组件</div>
      <ul>
        {/* 通过 Consumer 组件接收数据 */}
        <listContext.Consumer>
          {
            value => {
              return value.list.map(item => {
                return <li key={item}>{item}</li>
              })
            }
          }
        </listContext.Consumer>
      </ul>
    </div>
  )
}

四、兄弟组件通信(events)

import React, { PureComponent } from 'react';
import { EventEmitter } from 'events';

// 定义事件总线
const eventsBus = new EventEmitter();

// 子组件1
class Child1 extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      message: ''
    }
  }
  // 监听事件总线获取的值
  componentDidMount() {
    eventsBus.addListener('sayHello', this.handleSayHelloListener.bind(this))
  }
  handleSayHelloListener(message) {
    this.setState({
      message
    })
  }
  // 销毁监听事件
  componentWillUnmount() {
    eventsBus.removeListener('sayHello', this.handleSayHelloListener);
  }
  render() {
    return (
      <div>
        子组件1
        <h2>子组件2的消息:</h2>
        {this.state.message}
      </div>
    )
  }
}

// 子组件2
class Child2 extends PureComponent {
  render() {
    return (
      <div>
        子组件2
        <button onClick={() => this.sendMsg()}>发送消息</button>
      </div>
    )
  }
  // 从子组件 2 发送消息至子组件 1
  sendMsg() {
    eventsBus.emit('sayHello', '你好,我是子组件2', 666)
  }
}

class App extends PureComponent {
  render() {
    return (
      <div>
        <Child1 />
        <Child2 />
      </div>
    );
  }
}
export default App;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容