对于组件来说,通信无非两种,父子组件通信,和非父子组件通信
一、父子父子组件通信
1、父组件给子组件传值
对于父组件来说,props是他们之间的媒介
class Parent extends Component{
state = {
msg: 'start'
};
componentDidMount() {
setTimeout(() => {
this.setState({
msg: 'end'
});
}, 1000);
}
render() {
return <Child_1 msg={this.state.msg} />;
}
}
class Child_1 extends Component{
render() {
return <p>{this.props.msg}</p>
}
}
子组件通过接受父组件的props来获取父组件中的数据
2、子组件给父组件传值
途径是先在父组件中注册一个回调函数,子组件通过props获取到这一回调函数并执行
class Parent extends Component{
state = {
msg: 'start'
};
transferMsg(msg) {
this.setState({
msg
});
}
render() {
return <div>
<p>child msg: {this.state.msg}</p>
<Child_1 transferMsg = {msg => this.transferMsg(msg)} />
</div>;
}
}
class Child_1 extends Component{
componentDidMount() {
setTimeout(() => {
this.props.transferMsg('end')
}, 1000);
}
render() {
return <div>
<p>child_1 component</p>
</div>
}
}
这样在子组件中用传参的方式,获取到子组件中的数据,进而改变了父组件的状态
3、祖先组件给后代组件(就是组件之间的嵌套已经超过一层)
这样的话也还可以通过props来传值,但是一层一层的传有点麻烦,我们可以使用... 运算符(三个点是es6里面的剩余展开属性),以更简洁的方式传递给更深层级的子组件。通过这种方式,不用考虑性能的问题,通过 babel 转义后的 ... 运算符
性能和原生的一致
class Child_1 extends Component{
render() {
return <div>
<p>{this.props.msg}</p>
<Child_1_1 {...this.props}/>
</div>
}
}
class Child_1_1 extends Component{
render() {
return <p>{this.props.msg}</p>
}
}
二、非父子组件之间的传值
对于非父子组件来说缺少连接的纽带,很难通过props联系到一起(要是不是很远的话也能用,但是要是过深就特别麻烦),但是我们可以使用全局的一些机制来实现,比如react提供了一种上下文机制
class Brother1 extends React.Component{
constructor(props){
super(props);
this.state = {}
}
render(){
return (
<div>
<button onClick={this.context.refresh}>
更新兄弟组件
</button>
</div>
)
}
}
Brother1.contextTypes = {
refresh: React.PropTypes.any
}
class Brother2 extends React.Component{
constructor(props){
super(props);
this.state = {}
}
render(){
return (
<div>
{this.context.text || "兄弟组件未更新"}
</div>
)
}
}
Brother2.contextTypes = {
text: React.PropTypes.any
}
class Parent extends React.Component{
constructor(props){
super(props);
this.state = {}
}
getChildContext(){
return {
refresh: this.refresh(),
text: this.state.text,
}
}
refresh(){
return (e)=>{
this.setState({
text: "兄弟组件沟通成功",
})
}
}
render(){
return (
<div>
<h2>兄弟组件沟通</h2>
<Brother1 />
<Brother2 text={this.state.text}/>
</div>
)
}
}
Parent.childContextTypes = {
refresh: React.PropTypes.any,
text: React.PropTypes.any,
}
使用方法
使用getChildContext
方法将属性传递给子组件,并使用childContextTypes
声明传递数据类型,子组件中需要显式地使用contextTypes
声明需要用到的属性的数据类型。
需要传递进context参数才可以在constructor方法中使用context,要不然React将会报错。
在组件中,通过this.context访问context中的属性或方法。
未完待续。。。
关于组件之间的通信还有更好的方式,比如说用redux来管理数据流,之后单独整理关于redux的部分。