组件通信一直是 React 的重点内容,几乎写的每个 React 组件都离不开通信,所以掌握 React 通信的各种方法是学习 React 开发的必然道路。

父向子通信

1. props


const Child = ({ name }) => {
    <div>{name}</div>
}

class Parent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            name: 'zach'
        }
    }
    render() {
        return (
            <Child name={this.state.name} />
        )
    }
}

2. Instance Methods

通过调用子组件的 ref 来调用其方法通信。

class Child extends React.Component {
  myFunc() {
    return hello
  }
}

class Parent extends React.Component {
  componentDidMount() {
    var x = this.foo.myFunc()   // x is now 'hello'
  }
  render() {
    return (
      <Child
        ref={foo => {
          this.foo = foo
        }}
      />
    )
  }
}

子向父通信

1. 回调函数

比较常用的就是回调函数了,父组件传一个函数过去,子组件触发(可传参),进而达到通信。

const Child = ({ onClick }) => {
    <div onClick={() => onClick('zach')}>Click Me</div>
}

class Parent extends React.Component {
    handleClick = (data) => {
        console.log(Parent received value from child:  + data)
    }
    render() {
        return (
            <Child onClick={this.handleClick} />
        )
    }
}

2. 事件冒泡

这个是 JS 原生的特性,只要给父元素绑定个事件,嵌套在下面的子元素一旦触发,就会冒泡到父元素上的事件。

class Parent extends React.Component {
  render() {
    return (
      <div onClick={this.handleClick}>
         <Child />
      </div>
    );
  }
  handleClick = () => {
    console.log('clicked')
  }
}
function Child {
  return (
    <button>Click</button>
  );    
}

非父子通信

1. 提取到父组件

如果说两个组件不是父子关系,就不能通过 Props 或者 回调函数来通信了,但是可以把这两个不相关的组件套在一个公用父组件里,这样就可以在这个父组件里传回调让这两个子组件互相通信了。

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {count: 0}
  }
  setCount = () => {
    this.setState({count: this.state.count + 1})
  }
  render() {
    return (
      <div>
        <SiblingA
          count={this.state.count}
        />
        <SiblingB
          onClick={this.setCount}
        />
      </div>
    );
  }

}

深嵌套组件通信

1. Context

我们使用的 redux 就使用到了这个特性,在挂载 store 的时候,都得到应用最顶层的组件上设置,这样是为了让整个应用都可以共享 store 里面的数据,我们可以通过这个特性给一些复杂的组件,细分嵌套的组件提供更好的通信方式。

举个例子,我们想要给应用添加的全局色,不想一层一层的传递下去,就可以使用 Context

const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value=dark>
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

全局变量通信

我们可以将变量挂载到 window 上来实现整个应用的通信,在小程序中我们可以挂载到 wx 上来实现,简单的来说就是给应用一个全局的变量,这样在那样也可以访问的到,但是有个问题,全局变量非常的不安全,因为打开控制台就可以操控。

class ComponentA extends React.Component {
    handleClick = () => window.a = 'test'
    ...
}
class ComponentB extends React.Component {
    render() {
        return <div>{window.a}</div>
    }
}

Redux通信

一个复杂的应用,必然要使用到 Redux 这样的状态管理库,它可以很方便的追踪和管理整个应用的全局状态。

redux使用图

本文系作者 @ 原创发布在 极客猿小兵的博客。未经许可,禁止转载。


极客猿小兵 » React 组件通信

发表回复