react組件通信是一個(gè)常用功能扰楼,在做react項(xiàng)目中經(jīng)常遇到
React組件層級(jí)關(guān)系
在了解Reat組件通訊之前,先了解下React層級(jí)關(guān)系。
父子:parent與child1、child2、child1-1堡赔、child2-1
兄弟:child1與child2、child1-1與child1-2...
React組件通訊
組件間通信大體有下面幾種通訊方式:
1.父—>子:使用props
2.子—>父:使用props回調(diào)
3.兄弟組件通信:層層傳遞props设联;發(fā)布者訂閱者模式
4.非嵌套組件間通信:發(fā)布者訂閱者模式善已;redux
1.父—>子
父組件向子組件通信,用到比較多离例。在react中换团,數(shù)據(jù)流動(dòng)是單向的,父組件通過(guò)向子組件傳遞props進(jìn)行通信宫蛆,子組件得到props進(jìn)行相應(yīng)處理艘包。
patrent.js
import React,{Component} from 'react';
import Child1 from "./child1";//子頁(yè)面
export class Parent extends Component {
state = {
msg:'parent'
}
render(){
return(
<div>
<span>父組件通過(guò)props向子組件通信:</span>
<Child1 msg={this.state.msg}/>
</div>
)
}
}
export default Parent;
child1.js
import React,{Component} from 'react';
export class child1 extends Component {
render(){
return(
<span>{this.props.msg}</span> //通過(guò)props接收父組件信息
)
}
}
export default child1;
如果父組件與子組件之間不止一個(gè)層級(jí),如 parent 與child 耀盗、 child與child1_1 這樣的關(guān)系想虎,parent與child1_1通訊可通過(guò) es6中... 擴(kuò)展運(yùn)算符進(jìn)行通信
export class child1 extends Component {
render(){
return(
<div>
<span>{this.props.msg}</span><br/>
<Child1_1 {...this.props}/>//多個(gè)層級(jí)通過(guò)擴(kuò)展運(yùn)算符...
</div>
)
}
}
export class child1_1 extends Component {
render(){
return(
<span>parent與child1_1通信:{this.props.msg}</span>
)
}
}
2.子—>父
利用回調(diào)函數(shù)。
父組件向子組件傳遞 props 叛拷,只是父組件傳遞的是作用域?yàn)楦附M件自身的函數(shù)舌厨,子組件調(diào)用該函數(shù),將子組件想要傳遞的信息忿薇,作為參數(shù)裙椭,傳遞到父組件的作用域中。
parent.js
export class Parent extends Component {
constructor(props) {
super(props);
this.state = {
msg: 'parent',
child2Msg:''
};
}
msgCallback(msg) {
this.setState({
child2Msg:msg
});
}
render(){
return(
<div>
<div>
<span>父組件通過(guò)props向子組件通信:</span>
<Child1 msg={this.state.msg} />
</div>
<div>
<span>子組件通過(guò)回調(diào)函數(shù)向父組件通信:{this.state.child2Msg}</span><br/>
<Child2 msgCallback={child2 => this.msgCallback(child2)} />
</div>
</div>
)
}
}
child2.js
import React,{Component} from 'react';
export class child2 extends Component {
render(){
return(
<button onClick={()=>this.props.msgCallback("child2")}>child2</button>
)
}
}
export default child2;
對(duì)于層級(jí)比較深的子組件與父組件之間通訊煌恢,參照父組件與子組件通訊骇陈,仍可使用 ... 運(yùn)算符,將父組件的調(diào)用函數(shù)傳遞給子組件
3.兄弟組件通信
A.層層組件傳遞props:
對(duì)于沒有直接關(guān)系的兩個(gè)組件瑰抵,就如 child1 與 child2 之間,他們唯一的關(guān)聯(lián)就是擁有相同的父組件parent器联。參考之前父子通訊方式二汛,可以先通過(guò) child1 向 parent 組件進(jìn)行通訊婿崭,再由parent 向 child2 組件進(jìn)行通訊,在這里不貼代碼了肴颊。
不足:當(dāng)Parent 的 state 發(fā)生變化氓栈,會(huì)觸發(fā) Parent 及Parent 的子組件的生命周期,在各個(gè)組件中的 componentDidUpdate 方法均被觸發(fā)婿着。
B.發(fā)布者—訂閱者模式
這種方式可以避免上面的不足授瘦。發(fā)布者發(fā)布事件,訂閱者監(jiān)聽事件并做出反應(yīng)竟宋。
在這里需要一個(gè)事件系統(tǒng)提完,一個(gè)簡(jiǎn)單的事件系統(tǒng)是:
class Event {
constructor() {
this.listeners = {};
}
on(type, cb, mode) {
let cbs = this.listeners[type];
if (!cbs) {
cbs = [];
}
cbs.push(cb);
this.listeners[type] = cbs;
return () => {
this.remove(type, cb);
};
}
emit(type, ...args) {
const cbs = this.listeners[type];
if (Array.isArray(cbs)) {
for (let i = 0; i < cbs.length; i++) {
const cb = cbs[i];
if (typeof cb === 'function') {
cb(...args);
}
}
}
}
remove(type, cb) {
if (cb) {
let cbs = this.listeners[type];
cbs = cbs.filter(eMap => eMap.cb !== cb);
this.listeners[type] = cbs;
} else {
this.listeners[type] = null;
delete this.listeners[type];
}
}
}
export default new Event();
child1頁(yè)面發(fā)布事件
import React,{Component} from 'react';
import Child1_1 from './child1_1';
import Event from '../../utils/event'
export class child1 extends Component {
componentDidMount() {
setTimeout(() => {
// 發(fā)布事件
Event.emit('child1','child1發(fā)布消息')
}, 1000);
}
render(){
return(
<div>
<span>{this.props.msg}</span><br/>
<Child1_1 {...this.props}/>
</div>
)
}
}
export default child1;
child2頁(yè)面接收事件
componentDidMount() {
//接收事件
Event.on('child1', (msg) => {
this.setState({
msg
});
}
)
}
我們可以看到,child1 組件的 componentDidMount 中發(fā)布了事件,child2 組件對(duì)事件做出響應(yīng)丘侠,更新自身 state徒欣,在整個(gè)通訊過(guò)程中,只有 child2 發(fā)出了一次生命周期更新渲染蜗字。
4.redux
Redux是 JavaScript 狀態(tài)容器打肝,是第三方的狀態(tài)管理器,提供可預(yù)測(cè)化的狀態(tài)管理挪捕,是通訊的中間者粗梭。大中型項(xiàng)目可以使用redux,小項(xiàng)目就沒什么必要了级零。redux介紹的東西太多了断医,在這里我就不具體介紹了,感興趣的話妄讯,大家可以去了解下https://www.redux.org.cn/孩锡。
以上若有錯(cuò)誤或考慮不周之處,敬請(qǐng)指正亥贸,謝謝躬窜!