ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# 组件通信 ## 父组件 --> 子组件 ```jsx // 子组件: Child const Child = props =>{ return <p>{props.name}</p> } // 父组件 Parent const Parent = ()=>{ return <Child name="react"></Child> } ``` ## 子组件 --> 父组件: props+回调 ```jsx // 子组件 Child const Child = props =>{ const cb = msg =>{ return ()=>{ props.callback(msg) } } return ( <button onClick={cb("你好!")}>你好</button> ) } // 父组件 Parent class Parent extends Component { callback(msg){ console.log(msg) } render(){ return <Child callback={this.callback.bind(this)}></Child> } } ``` ## 跨级组件通信: 父组件 --> 孙组件 * 使用props,利用中间组件层层传递,中间每一层组件都要传递props,增加了复杂度。 * context相当于一个大容器,把要通信的内容放在这个容器中,对于跨越多层的全局数据使用context实现。 ```jsx // Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据 const BatteryContext = createContext(); // 子组件的子组件 class GrandChild extends Component { render(){ return (<BatteryContext.Consumer> {color => <h1 style={{"color":color}}>我是红色的:{color}</h1>} </BatteryContext.Consumer>) } } // 子组件 const Child = () =>{return ( <GrandChild/> ) } // 父组件 class Parent extends Component { state = { color:"red" } render(){ const {color} = this.state return (<BatteryContext.Provider value={color}><Child></Child></BatteryContext.Provider>) } } ``` ## onRef 通过props 将子组件的组件实例(this)当作参数,通过回调传到父组件. ` this.props.onRef(this)` 然后在父组件就可以拿到子组件的实例,拿到了它的实例就可以调用它的方法 `sonRef = (ref) => { this.child = ref } ... <Son onRef={this.sonRef} /> ` ```js // 父组件 import React from 'react' import Son from './son' import { Button } from 'antd' class Father extends React.Component { child: any constructor(props) { super(props) } sonRef = (ref) => { this.child = ref } // 在这里拿到子组件的实例 clearSonInput = () => { this.child.clearInput() } render() { return ( <div> <Son onRef={this.sonRef} /> <Button type='primary' onClick={this.clearSonInput}> 清空子组件的input </Button> </div> )} } export default Father // 子组件 import React from 'react' import { Button } from 'antd' interface IProps { onRef: any } class Son extends React.Component<IProps> { constructor(props) { super(props) } componentDidMount() { this.props.onRef(this) } // 在这将子组件的实例传递给父组件this.props.onRef()方法 state = { info: 'son',} handleChange = (e) => { this.setState({ info: e.target.value, })} clearInput = () => { this.setState({ info: '', }) } render() { return ( <div> <div>{this.state.info}</div> <input type='text' onChange={this.handleChange} /> </div> )} } export default Son ``` ## ref `ref`是react提供的一个属性,通过它访问DOM节点或者组件 `React.createRef()` ```js // 父组件 import React from 'react' import Son from './son' import { Button } from 'antd' class Father extends React.Component { son: any constructor(props) { super(props) this.son = React.createRef() // 在此处创建ref } clearSonInput = () => { const { current } = this.son // 注意,这里必须通过 this.son.current拿到子组件的实例 current.clearInput() } render() {return ( <div> <Son ref={this.son} /> <Button type='primary' onClick={this.clearSonInput}> 清空子组件的input</Button> </div> )} } export default Father // 子组件 import React from 'react' import { Button } from 'antd' class Son extends React.Component { constructor(props) { super(props) } state = { info: 'son', } handleChange = (e) => { this.setState({ info: e.target.value, })} clearInput = () => { this.setState({ info: '',}) } render() { return ( <div> <div>{this.state.info}</div> <input type='text' onChange={this.handleChange} /> </div> )} } export default Son ``` ## 非嵌套组件通信 * 可以通过redux等进行全局状态管理 * 兄弟组件通信: 找到这两个兄弟节点共同的父节点, 结合父子间通信方式进行通信 - **events(发布订阅)** 安装: yarn add events 或者 安装 npm install pubsub-js --save ```js // import PubSub from 'pubsub-js' const PubSub = require('pubsub-js'); //订阅消息 var token = PubSub.subscribe('MY TOPIC', (msg, data) => { console.log( msg, data ); }); //发布消息 PubSub.publish('MY TOPIC', 'hello world!'); ``` ```jsx // event.ts import { EventEmitter } from 'events' export default new EventEmitter() // 发布者 通过emit事件触发方法,发布订阅消息给订阅者 import React from 'react' import Son1 from './son1' import { Button } from 'antd' import emitter from './event' class Father extends React.Component { son: any constructor(props) { super(props) } handleClick = () => { //emit事件触发方法,将事件处理函数作为参数传入 emitter.emit('info', '我是来自father的 info') } render() {return ( <div> <Button type='primary' onClick={this.handleClick}> 点击发布</Button> <Son1 /> </div> )} } export default Father // emitter.addListener(事件名,函数名)--事件监听(订阅) // emitter.removeListener--事件销毁(取消订阅) import React from 'react' import { Button } from 'antd' import emitter from './event' class Son1 extends React.Component { constructor(props) { super(props) } state = { info: ''} componentDidMount() { // 在组件挂载完成后开始监听 emitter.addListener('info', (info) => { this.setState({info: 'Son1收到消息--' + info }) }) } componentWillUnmount() { // 组件销毁前移除事件监听 emitter.removeListener('info', (info) => { this.setState({info: 'Son1即将移除事件监听--' + info}) }) } render() {return (<div><div>{this.state.info}</div></div>)} } export default Son1 ```