React组件通信
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') } }
语雀链接🔗 https://www.yuque.com/suihangadam
归来卧占楼千尺,梦落沧波明月舟。