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') } }