react组件通信是一个常用功能,在做react项目中经常遇到
React组件层级关系
在了解Reat组件通讯之前,先了解下React层级关系。
父子:parent与child1、child2、child1-1、child2-1
兄弟:child1与child2、child1-1与child1-2...
React组件通讯
组件间通信大体有下面几种通讯方式:
1.父—>子:使用props
2.子—>父:使用props回调
3.兄弟组件通信:层层传递props;发布者订阅者模式
4.非嵌套组件间通信:发布者订阅者模式;redux
1.父—>子
父组件向子组件通信,用到比较多。在react中,数据流动是单向的,父组件通过向子组件传递props进行通信,子组件得到props进行相应处理。
patrent.js
import React,{Component} from 'react';
import Child1 from "./child1";//子页面
export class Parent extends Component {
state = {
msg:'parent'
}
render(){
return(
<div>
<span>父组件通过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> //通过props接收父组件信息
)
}
}
export default child1;
如果父组件与子组件之间不止一个层级,如 parent 与child 、 child与child1_1 这样的关系,parent与child1_1通讯可通过 es6中... 扩展运算符进行通信
export class child1 extends Component {
render(){
return(
<div>
<span>{this.props.msg}</span><br/>
<Child1_1 {...this.props}/>//多个层级通过扩展运算符...
</div>
)
}
}
export class child1_1 extends Component {
render(){
return(
<span>parent与child1_1通信:{this.props.msg}</span>
)
}
}
2.子—>父
利用回调函数。
父组件向子组件传递 props ,只是父组件传递的是作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中。
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>父组件通过props向子组件通信:</span>
<Child1 msg={this.state.msg} />
</div>
<div>
<span>子组件通过回调函数向父组件通信:{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;
对于层级比较深的子组件与父组件之间通讯,参照父组件与子组件通讯,仍可使用 ... 运算符,将父组件的调用函数传递给子组件
3.兄弟组件通信
A.层层组件传递props:
对于没有直接关系的两个组件,就如 child1 与 child2 之间,他们唯一的关联就是拥有相同的父组件parent。参考之前父子通讯方式,可以先通过 child1 向 parent 组件进行通讯,再由parent 向 child2 组件进行通讯,在这里不贴代码了。
不足:当Parent 的 state 发生变化,会触发 Parent 及Parent 的子组件的生命周期,在各个组件中的 componentDidUpdate 方法均被触发。
B.发布者—订阅者模式
这种方式可以避免上面的不足。发布者发布事件,订阅者监听事件并做出反应。
在这里需要一个事件系统,一个简单的事件系统是:
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页面发布事件
import React,{Component} from 'react';
import Child1_1 from './child1_1';
import Event from '../../utils/event'
export class child1 extends Component {
componentDidMount() {
setTimeout(() => {
// 发布事件
Event.emit('child1','child1发布消息')
}, 1000);
}
render(){
return(
<div>
<span>{this.props.msg}</span><br/>
<Child1_1 {...this.props}/>
</div>
)
}
}
export default child1;
child2页面接收事件
componentDidMount() {
//接收事件
Event.on('child1', (msg) => {
this.setState({
msg
});
}
)
}
我们可以看到,child1 组件的 componentDidMount 中发布了事件,child2 组件对事件做出响应,更新自身 state,在整个通讯过程中,只有 child2 发出了一次生命周期更新渲染。
4.redux
Redux是 JavaScript 状态容器,是第三方的状态管理器,提供可预测化的状态管理,是通讯的中间者。大中型项目可以使用redux,小项目就没什么必要了。redux介绍的东西太多了,在这里我就不具体介绍了,感兴趣的话,大家可以去了解下https://www.redux.org.cn/。
以上若有错误或考虑不周之处,敬请指正,谢谢!
网友评论