React基础(三)组件间通信

3,984 阅读3分钟

组件间通信

父组件向子组件通信

这是最简单也是最常见的一种通信方式。父组件通过向组件间传递props,组件得到props后进行相应的处理。

父组件:

import Child from './Child'
class Father extends Component {
	render(){
  	return(
    	<Child  title = "子组件的title 由父组件传递" />
    )
  }
}

子组件:

class Child extends Component{
  constructor(){
    super(props)
  }
  
	render(){
  	return <h1>{ this.props.title }</h1>
  }
}

子组件向父组件通信

child组件通知父组件,主要依靠parent传下来的回调函数执行,改变parent组件的状态。
场景1: 子组件要修改父组件的状态state
方法: 父组件传递一个函数 作为子组件的props,这个函数包含父组件的setState方法,并且接收一个参数,表示父组件 新的state

class Father extends Component {
	constructor(){
  	super()
    this.state ={ value:'' } 
  }
  // 作为参数要传递的 函数 
  setValue = value =>{
  	this.setState({
    	value
    })
  }
  render(){
  	return (
    	<div>
      	<div>我是父组件,value是:{ this.state.value }<div>
      	<Child setValue = { this.setValue } />
      </div>
    )
  }
}
class Child extends Component {
  constructor(){
  	super(props)
    this.state ={ inputValue:''}
  }
  // 监听输入框变化
  handleInputChange = e => {
  	this.setState({
    	inputValue:e.target.value
    })
  }
  handleDivClick = () => {
    // 从props接收一个函数 该函数中包含父组件 的setState方法
  	const { setValue } = this.props
    // 将新的数据 作为参数  执行这个函数
    setValue(this.state.inputValue)
    // 执行这个函数 父组件的state发生变化,触发re-render
  }
  
	render(){
  	return (
    	<div>
      	<div>我是子组件</div>
      	<input onChange ={ this.handleInputChange }>
      	<div onClick ={ this.handleDivClick }>点击就能改变父组件的状态</div>
      </div>
    )
  }
}

场景2 state定义在子组件中
有时候父组件只是需要拿到子组件的state
因此可以在父组件定义一个函数,接收子组件的state,然后将这个函数以props的形式传递给子组件。
子组件通过this.prop.属性名,拿到这个函数,将子组件本身的state作为函数参数,然后执行这个函数即可。

// parent

class Parent extends Component {

  onChange = value => {
    console.log(value, '来自 child 的 value 变化');
  }

  render() {
    return (
      <div>
        <div>我是parent
        <Child onChange={this.onChange} />
      </div>
    );
  }
}
class Child extends Component {

  constructor() {
    super();
    this.state = {
      childValue: ''
    }
  }

  childValChange = e => {
    this.childVal = e.target.value;
  }

  childValDispatch = () => {
    const { onChange } = this.props;
    this.setState({
      childValue: this.childVal,
    }, () => { onChange(this.state.childValue) })
  }

  render() {
    return (
      <div>
        我是Child
        <div className="card">
          state 定义在 child
          <input onChange={this.childValChange} />
          <div className="button" onClick={this.childValDispatch}>通知</div>
        </div>
      </div>
    );
  }
}

兄弟组件间通信

方式1 依赖共同的container

有时候出现页面中的某两部分通信,组件并不是父子级别,没有嵌套关系的时候,这种时候通常是依赖共有的顶级container处理或者是第三方的状态管理器。
原理:
兄弟A的value发生变化,分发的时候把value值告诉一个中间者C,C会自动告诉B,实现B的自动render。

// container
class Container extends Component {
  constructor() {
    super();
    this.state = {
      value: '',
    }
  }
  
  setValue = value => {
    this.setState({
      value,
    })
  }

  render() {
    return (
      <div>
        <A setValue={this.setValue}/>
        <B value={this.state.value} />
      </div>
    );
  }
}
// 兄弟A
class A extends Component {

  handleChange = (e) => {
    this.value = e.target.value;
  }

  handleClick = () => {
    const { setValue } = this.props;
    setValue(this.value);
  }

  render() {
    return (
      <div className="card">
        我是Brother A, <input onChange={this.handleChange} />
        <div className="button" onClick={this.handleClick}>通知</div>
      </div>
    )
  }
}
// 兄弟B
const B = props => (
  <div className="card">
    我是Brother B, value是:
    {props.value}
  </div>
);
export default B;

利用一个共同的container,兄弟A根据子组件向父组件传值的方式,将自己的state更新到container中,而兄弟B则根据父祖件传值给子组件的方式,直接从props拿到新的state。

方式2 利用Context

上面的方式,如果嵌套少还可以,如果嵌套多层,就很复杂了。每一层组件都要传递一次。
参考 React基础(4) Context上下文