這篇文章將為大家詳細(xì)講解有關(guān)如何解決React中組件通信問(wèn)題,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
專業(yè)領(lǐng)域包括成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、電子商務(wù)商城網(wǎng)站建設(shè)、微信營(yíng)銷(xiāo)、系統(tǒng)平臺(tái)開(kāi)發(fā), 與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開(kāi)發(fā)公司不同,創(chuàng)新互聯(lián)的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷(xiāo)的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶提供全網(wǎng)互聯(lián)網(wǎng)整合方案。父子組件
父 → 子
parent組件傳給child組件,符合react的單向數(shù)據(jù)流理念,自上到下傳遞props。
// 父組件 class Parent extends Component { constructor() { super(); this.state = { value: '', } } handleChange = e => { this.value = e.target.value; } handleClick = () => { this.setState({ value: this.value, }) } render() { return (我是parent); } }通知
// 子組件 class Child extends Component { render() { const { value } = this.props; return (我是Child,得到傳下來(lái)的值:{value}); } }
父組件做的就是定義好 state ,定義好事件函數(shù),input onChange 的時(shí)候,去緩存 value 值,然后點(diǎn)擊 button 的時(shí)候,改變 state , 子組件只負(fù)責(zé)展示 value 。
子 → 父
child 組件通知 parent 組件, 主要是依靠 parent 傳下來(lái)的 callback 函數(shù)執(zhí)行,改變 parent 組件的狀態(tài),或者把 child 自己的 state 通知 parent 。分兩種情況:
state 定義在 parent 組件
// parent class Parent extends Component { constructor() { super(); this.state = { value: '', } } setValue = value => { this.setState({ value, }) } render() { return (); } }我是parent, Value是:{this.state.value}
class Child extends Component { handleChange = e => { this.value = e.target.value; } handleClick = () => { const { setValue } = this.props; setValue(this.value); } render() { return (我是Child); } }state 定義在 parent通知
parent 組件把改變 state 的 setValue 函數(shù)傳給 child ,child 組件自己處理內(nèi)部的狀態(tài)(這里是表單的value值),當(dāng) child 組件分發(fā)消息的時(shí)候, 執(zhí)行 parent 的 setValue 函數(shù),從而改變了 parent 的 state,state發(fā)生變化, parent 組件執(zhí)行 re-render 。
state 定義在 child 組件
// parent class Parent extends Component { onChange = value => { console.log(value, '來(lái)自 child 的 value 變化'); } render() { return (我是parent); } } class Child extends Component { constructor() { super(); this.state = { childValue: '' } } childValChange = e => { this.childVal = e.target.value; } childValDispatch = () => { const { onChange } = this.props; this.setState({ childValue: this.childVal, }, () => { onChange(this.state.childValue) }) } render() { return (我是Child); } }state 定義在 child通知有時(shí)候 state 是需要定義在 child 組件的,比如彈窗, CheckBox 這種開(kāi)關(guān)性質(zhì)的,邏輯是重復(fù)的,state 定義在組件內(nèi)部更好維護(hù), 復(fù)用性更好。但是 child 的 state 是需要告知我的 parent 組件的, 同樣還是執(zhí)行 parent 傳下來(lái)的 change 函數(shù)。
兄弟組件
有時(shí)候可能出現(xiàn)頁(yè)面中的某兩部分通信,比如省市的級(jí)聯(lián)選擇,點(diǎn)擊 button 改變顏色等等,組件并不是父子級(jí),沒(méi)有嵌套關(guān)系的時(shí)候。這種時(shí)候通常是依賴共有的頂級(jí) Container 處理或者第三方的狀態(tài)管理器。其實(shí)原理都是相通的,兄弟 A 的 value 發(fā)生變化,分發(fā)的時(shí)候把 value 值告訴一個(gè)中間者 C ,C 會(huì)自動(dòng)告知 B,實(shí)現(xiàn) B 的自動(dòng)render 。
利用共有的Container
// container class Container extends Component { constructor() { super(); this.state = { value: '', } } setValue = value => { this.setState({ value, }) } render() { return ( ); } }// 兄弟A class A extends Component { handleChange = (e) => { this.value = e.target.value; } handleClick = () => { const { setValue } = this.props; setValue(this.value); } render() { return (我是Brother A,) } }通知// 兄弟B const B = props => (我是Brother B, value是: {props.value}); export default B;組件 A 中的表單 value 值,告知了父級(jí) Container 組件(通過(guò) setValue 函數(shù)改變 state),組件 B 依賴于 Container 傳下來(lái)的 state,會(huì)做出同步更新。這里的中間者是 Container。
利用Context
上面的方式,如果嵌套少還可以,如果嵌套特別多,比如一級(jí)導(dǎo)航欄下的二級(jí)導(dǎo)航欄下的某個(gè)按鈕,要改變頁(yè)面中 content 區(qū)域的 table 里的某個(gè)列的值...他們同屬于一個(gè) page 。這樣傳遞 props 就會(huì)很痛苦,每一層組件都要傳遞一次。
// 頂級(jí)公共組件
class Context extends Component {constructor() { super(); this.state = { value: '', }; } setValue = value => { this.setState({ value, }) } getChildContext() { // 必需 return { value: this.state.value, setValue: this.setValue, }; } render() { return (); } } // 必需 Context.childContextTypes = { value: PropTypes.string, setValue: PropTypes.func, }; // A 的 parent class AParent extends Component { render() { return ( ); } } // A class A extends Component { handleChange = (e) => { this.value = e.target.value; } handleClick = () => { const { setValue } = this.context; setValue(this.value); } render() { return (我是parentA 下的 A,); } } // 必需 A.contextTypes = { setValue: PropTypes.func, };通知// B 的 parent class BParent extends Component { render() { return (); } } // B class B extends Component { render() { return (我是parentB 下的 B, value是: {this.context.value}); } } B.contextTypes = { value: PropTypes.string, };組件 A 仍是 消息的發(fā)送者,組件 B 是接收者, 中間者是 Context 公有 Container 組件。context是官方文檔的一個(gè) API ,通過(guò) getChildContext 函數(shù)定義 context 中的值,并且還要求 childContextTypes 是必需的。這樣屬于這個(gè) Container 組件的子組件,通過(guò) this.context 就可以取到定義的值,并且起到跟 state 同樣的效果。中間者其實(shí)還是 Container,只不過(guò)利用了上下文這樣的 API ,省去了 props 的傳遞。另外:這個(gè)功能是實(shí)驗(yàn)性的,未來(lái)可能會(huì)有所改動(dòng)。
發(fā)布訂閱
這種一個(gè)地方發(fā)送消息,另一個(gè)地方接收做出變化的需求,很容易想到的就是觀察者模式了。具體的實(shí)現(xiàn)會(huì)有很多種,這里我們自己寫(xiě)了一個(gè) EventEmitter 的類(lèi)(其實(shí)就是仿照 node 中的 EventEmitter 類(lèi)),如果不了解觀察者,可以看我的另一篇文章 觀察者模式 。
// 發(fā)布訂閱類(lèi) class EventEmitter { _event = {} // on 函數(shù)用于綁定 on(eventName, handle) { let listeners = this._event[eventName]; if(!listeners || !listeners.length) { this._event[eventName] = [handle]; return; } listeners.push(handle); } // off 用于移除 off(eventName, handle) { let listeners = this._event[eventName]; this._event[eventName] = listeners.filter(l => l !== handle); } // emit 用于分發(fā)消息 emit(eventName, ...args) { const listeners = this._event[eventName]; if(listeners && listeners.length) { for(const l of listeners) { l(...args); } } } } const event = new EventEmitter; export { event };// Container import A from './a'; import B from './b'; const Listener = () => { return ( ); }; export default Listener;// 兄弟組件 A import { event } from './eventEmitter'; class A extends Component { handleChange = e => { this.value = e.target.value; } handleClick = () => { event.emit('dispatch', this.value); } render() { return (我是Brother A,) } }通知// 兄弟組件 B import { event } from './eventEmitter'; class B extends Component { state = { value: '' } componentDidMount() { event.on('dispatch', this.valueChange); } componentWillUnmount() { event.off('dispatch', this.valueChange); } valueChange = value => { this.setState({ value, }) } render() { return (我是Brother B, value是: {this.state.value}); } }仍然是組件 A 用于分發(fā)消息,組件 B 去接收消息。這里的中間者其實(shí)就是 event 對(duì)象。需要接收消息的 B 去訂閱 dispatch 事件,并把回調(diào)函數(shù) valueChange 傳入,另外 B 定義了自己的 state,方便得到 value 值的時(shí)候自動(dòng)渲染。組件 A 其實(shí)就是把內(nèi)部的表單 value 在點(diǎn)擊的時(shí)候分發(fā),發(fā)布事件,從而 B 中的 valueChange 執(zhí)行,改變 state。這種方式比較方便,也更直觀,不需要借助 Container 組件去實(shí)現(xiàn),省去了很多邏輯。
Redux || Mobx
Redux 或者 Mobx 是第三方的狀態(tài)管理器,是這里我們通信的中間者。大型項(xiàng)目最直接的就是上庫(kù)... 更方便,更不容易出錯(cuò)。 但其實(shí)小項(xiàng)目就沒(méi)什么必要了。東西比較多,這里不再闡述它們的實(shí)現(xiàn)和做了什么。
關(guān)于“如何解決React中組件通信問(wèn)題”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
當(dāng)前名稱:如何解決React中組件通信問(wèn)題-創(chuàng)新互聯(lián)
分享鏈接:http://weahome.cn/article/gseoc.html