9

React组件通信

 3 years ago
source link: http://www.cnblogs.com/suihang/p/13701497.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

React间组件间通信有如下几种方式:

  • 父组件向子组件通信
  • 子组件向父组件通信
  • 跨级组件通信
  • 非嵌套关系的组件通信

父组件向子组件通信

父组件直接通过props向子组件传递需要的信息

// 子组件
const Child = props => {
    return <p>{props.name}</p>
}
// 父组件
const Parent = ()=>{
    return <Child name='哈哈哈'/>
}

子组件向父组件通信

props+回调。即父组件通过props传递方法下去,子组件调用这个方法。

// 子组件
const Child = props=> {
  const test = msg=> {
    return () => {
        props.callback(msg);
    }
  }
    return (
    <Button onClick={test('子组件的数据')}>按钮</Button>
  )
}
// 父组件
class parent extends Component{
    callback = (msg) => {
    console.log('子组件的数据:' + msg);
  }
  render(){
    return <Child callback={this.callback}>
  }
}

跨级组件通信

  • 使用props进行多级传递,但是增加了复杂度
  • 使用context,context相当于一个大容器,不管多少层都可以轻松拿到,对于跨越多层的数据可以采用这个方案。

官网Context详细介绍 https://react.docschina.org/docs/context.html

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。
  // React 会往上找到最近的 theme Provider,然后使用它的值。
  // 在这个例子中,当前的 theme 值为 “dark”。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

非嵌套关系的组件通信

  • 使用redux等状态管理工具
  • 可以使用自定义事件通信(发布订阅模式)

设置一个event文件

      class Event{
        constructor() {
          this.eventList = [];
        }
        // 绑定事件
        $on = (eventName, cb)=> {  
          // 判断该类型的事件是否存在,若存在则添加
          let lists = this.eventList[eventName];
          if(!lists){
            this.eventList[eventName] = []
          }
          this.eventList[eventName].push(cb)
        }
        // 触发事件
        $emit = (eventName, params) => {
          // 先判断事件类型是否存在
          let lists = this.eventList[eventName];
          if(!lists) {
            throw new Error('无此事件类型')
          }
          // 若存在则执行
          lists.forEach((item)=>{
            item(params);
          });
        }
        
        $off = (eventName, cb) => {
          let lists = this.eventList[eventName];
          if(lists){
            // 若第二个参数存在,则删除该类型下指定的方法,若不存在则删除整个类型
            if(!cb){
              this.eventList[eventName] = []
            }else{
              this.eventList[eventName] = lists.filter((item)=>{
                return item !=cb;
              })
            }
          }
        }
      }

使用示例

a文件里触发

import Event from 'event'
class A extends React.Component {
    componentDidMount() {
        Event.on('data1Change', this.handleData1Change)
    }
    handleData1Change = ()=>{
        console.log('测试')
    }
}

b文件里触发

import Event from 'event'
class B extends React.Component {
    handleUpdateData = () => {
       Event.emit('data1Change')
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK