React/组件通信
组件通信可以分为以下几种:
- 父组件向子组件通信
- 子组件向父组件通信
- 跨级组件的通信及context
- 没有嵌套关系的组件通信
父组件向子组件通信
父组件通过props向子组件传递需要的信息。
子组件向父组件通信
子组件调用porp中传来的父组件的方法达到通信的目的
跨级组件的通信
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
// 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(props) { 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} />; } }
没有嵌套关系的组件通信
使用events库,收信方在componentDidMount里面注册监听事件,在componentUnMount里销毁该事件。发信方则使用emit方法即可发出通讯消息。(切记,有注册,就得有销毁)
// 使用示例 class List1 extends React.Component{ constructor(props) { super(props) this.state = { text: 'list1' } } render() { return ( <div>{ this.state.text }</div> ) } componentDidMount() { this.eventEmitter = ee.addListener('changeMessage', (msg) => { this.setState({ text: msg }) }) } componentWillUnmount() { ee.removeListener(this.eventEmitter) } } class List2 extends React.Component{ handleClick(message) { ee.emit('changeMessage', message) } render() { return ( <button onClick={ this.handleClick.bind(this, '哈哈')}>点点点</button> ) } }