React之入门第(三)篇

63 阅读2分钟

组件间通信

  1. 父传子
实现步骤
  1. 父组件提供要传递的数据  -  state
  2. 给子组件标签添加属性值为 state中的数据
  3. 子组件中通过 props 接收父组件中传过来的数据
    1. 类组件使用this.props获取props对象
    2. 函数式组件直接通过参数获取props对象

image.png 函数式组件

// 父组件
function ParentComponent() {
  const parentData = '父组件数据';
  return <ChildComponent parentData={parentData} />;
}
 
// 子组件
function ChildComponent(props, ref) {
  return <div>{props.parentData}</div>;
}

类组件

import React from 'react'

// 函数式子组件
function FSon(props) {
  console.log(props)
  return (
    <div>
      子组件1
      {props.msg}
    </div>
  )
}

// 类子组件
class CSon extends React.Component {
  render() {
    return (
      <div>
        子组件2
        {this.props.msg}
      </div>
    )
  }
}
// 父组件
class App extends React.Component {
  state = {
    message: 'this is message'
  }
  render() {
    return (
      <div>
        <div>父组件</div>
        <FSon msg={this.state.message} />
        <CSon msg={this.state.message} />
      </div>
    )
  }
}

export default App
  1. 子传父
实现步骤
  1. 父组件提供一个回调函数 - 用于接收数据
  2. 将函数作为属性的值,传给子组件
  3. 子组件通过props调用回调函数
  4. 将子组件中的数据作为参数传递给回调函数

image.png 函数式组件

// 父组件
function ParentComponent() {
  const [value, setValue] = useState('');
 
  const handleChildValue = (newValue) => {
    setValue(newValue);
  };
 
  return (
    <div>
      <ChildComponent onChangeValue={handleChildValue} />
      <p>从子组件接收的值:{value}</p>
    </div>
  );
}
 
// 子组件
function ChildComponent({ onChangeValue }) {
  const [childValue, setChildValue] = useState('');
 
  const handleChange = (event) => {
    const newValue = event.target.value;
    // 改变数值
    setChildValue(newValue);
    // 调用父组件方法并传值
    onChangeValue(newValue);
  };
 
  return (
    <input type="text" value={childValue} onChange={handleChange} />
  );
}

类组件

import React from 'react'

// 子组件
function Son(props) {
  function handleClick() {
    // 调用父组件传递过来的回调函数 并注入参数
    props.changeMsg('this is newMessage')
  }
  return (
    <div>
      {props.msg}
      <button onClick={handleClick}>change</button>
    </div>
  )
}


class App extends React.Component {
  state = {
    message: 'this is message'
  }
  // 提供回调函数
  changeMessage = (newMsg) => {
    console.log('子组件传过来的数据:',newMsg)
    this.setState({
      message: newMsg
    })
  }
  render() {
    return (
      <div>
        <div>父组件</div>
        <Son
          msg={this.state.message}
          // 传递给子组件
          changeMsg={this.changeMessage}
        />
      </div>
    )
  }
}

export default App
  1. 兄弟组件传值
实现步骤
  1. 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
    • 提供共享状态
    • 提供操作共享状态的方法
  1. 要接收数据状态的子组件通过 props 接收数据
  2. 要传递数据状态的子组件通过props接收方法,调用方法传递数据

image.png

import React from 'react'

// 子组件A
function SonA(props) {
  return (
    <div>
      SonA
      {props.msg}
    </div>
  )
}
// 子组件B
function SonB(props) {
  return (
    <div>
      SonB
      <button onClick={() => props.changeMsg('new message')}>changeMsg</button>
    </div>
  )
}

// 父组件
class App extends React.Component {
  // 父组件提供状态数据
  state = {
    message: 'this is message'
  }
  // 父组件提供修改数据的方法
  changeMsg = (newMsg) => {
    this.setState({
      message: newMsg
    })
  }

  render() {
    return (
      <>
        {/* 接收数据的组件 */}
        <SonA msg={this.state.message} />
        {/* 修改数据的组件 */}
        <SonB changeMsg={this.changeMsg} />
      </>
    )
  }
}

export default App
  1. 跨组件通信 - Context
实现步骤
  1. 创建Context对象 导出 Provider 和 Consumer对象
const { Provider, Consumer } = createContext()
  1. 使用Provider包裹上层组件提供数据
<Provider value={this.state.message}>
    {/* 根组件 */}
</Provider>
  1. 需要用到数据的组件使用Consumer包裹获取数据
<Consumer >
    {value => /* 基于 context 值进行渲染*/}
</Consumer>
代码实现
import React, { createContext }  from 'react'

// 1. 创建Context对象 
const { Provider, Consumer } = createContext()


// 3. 消费数据
function ComC() {
  return (
    <Consumer >
      {value => <div>{value}</div>}
    </Consumer>
  )
}

function ComA() {
  return (
    <ComC/>
  )
}

// 2. 提供数据
class App extends React.Component {
  state = {
    message: 'this is message'
  }
  render() {
    return (
      <Provider value={this.state.message}>
        <div className="app">
          <ComA />
        </div>
      </Provider>
    )
  }
}

export default App