React兄弟、父子元素之间的通信

React元素之间的通信主要由下面几种方式 
1、 Redux 
2、 EventEmitter 
3、 通过props进行通信(需要有嵌套关系)

子元素到父元素

父子元素之间的通信主要靠props,这个方法既简单,又好用,所以可以使用这种方法的时候就直接用好了。 
首先有这样的一个React DOM结构:

<div className="passage">
<NavBar />
<Passage />
</div>

渲染外层的div元素的时候,需要进行两个子组件的渲染,其中Passage组件的加载内容取决于NavBar当前的内容或者被点击后的内容,这里可以首先实现父元素和NavBar之间的通信过程,设置一个句柄,来帮助进行通信。

constructor (props) {
super(props);
this.state = {
currentPassage: ""
}
this.refreshCurrentPassage = this.refreshCurrentPassage.bind(this);
} refreshCurrentPassage(cp) {
this.setState({
currentPassage: cp
});
}

上面的refreshCurrentPassage函数是这个通信过程的关键,我们将这个函数绑定当前父元素的this对象,并且将这个函数通过props传递给子元素:

 render() {
return (
<div className="passage">
<NavBar refreshCurrentPassage={this.refreshCurrentPassage} />
<Passage currentPassage={this.state.currentPassage}/>
</div>
);
}

子元素在其生命周期的componentDidMount阶段通过ajax获取当前页信息并且调用这个函数,将消息传递给父元素,这里需要注意React的生命周期,componentDidMount在官方给出的解释是:

Invoked once, only on the client (not on the server), immediately after the initial rendering occurs.

注意是在初始化渲染之后执行一次的。如果你还有其他特殊需求的话可以在其他阶段来调用这个函数。

class NavUl extends React.Component {
constructor (props) {
super(props);
this.state = {
passage: []
}
} componentDidMount() {
//在ajax请求成功之后调用一次更新父元素状态的函数,来完成一次父子元素之间的通信
$.ajax({
url: "../resources/data/passage.json",
success: (data) => {
this.setState({
passage: data.passages
});
this.props.refreshCurrentPassage(data.passages[0].passageName);
}、
});
} render() {
let liArray = [];
this.state.passage.forEach((value,index) => {
let liEle = <li key={value.passageName.toString()}>
<a>
{value.passageName}({value.letterNum})&nbsp;author:{value.author}
</a>
</li>
liArray.push(liEle);
});
return (
<ul>
{liArray}
</ul>
)
}
} class NavBar extends React.Component {
constructor (props) {
super(props);
} render() {
return (
<nav>
<NavUl refreshCurrentPassage={this.props.refreshCurrentPassage}/>
</nav>
);
}
}

父元素到子元素

父元素到子元素的状态通信更加简单了,可以直接使用props来进行传递。

//父元素的render函数
render() {
return (
<div className="passage">
<NavBar refreshCurrentPassage={this.refreshCurrentPassage} />
<Passage currentPassage={this.state.currentPassage}/>
</div>
);
}

通过将自己的state的currentPassage属性传递给子元素的一个属性,也就是props对象,来告诉子元素加载某个模块。

class Passage extends React.Component {
constructor (props) {
super(props); this.state = {
passage: ""
} }
//子元素通过自己的this.props对象来进行访问,可以直接得到父元素传递的消息
componentWillReceiveProps (nextProps) {
let passageName = nextProps.currentPassage;
passageName = passageName.toLowerCase().replace(" ", "");
$.ajax({
url: "../resources/data/" + passageName + ".json",
success: (data) => {
this.setState({
passage: data.passageContent
});
}
});
} render() {
return (
<article>
<p>
{this.state.passage}
</p>
</article>
);
}
}

兄弟元素之间

上面的两个部分组合起来刚好就完成了兄弟元素之前的通信,其中一个子元素通过调用父元素传递过来的函数this.props.refreshCurrentPassage来修改父元素状态,然后在父元素状态修改之后,另外一个子元素的this.props会发生变化,从而触发重新渲染。这里需要注意的是React组件的声明周期,父元素到子元素通信由于可能需要多次渲染,所以使用了声明周期中的componentWillReceiveProps阶段来进行内容加载。在官方文档中是这么介绍这个阶段的:

Invoked when a component is receiving new props. This method is not called for the initial render.

也就是在一个组件接收了新的属性(props)触发的,这个方法不会在初始化渲染的时候触发。并且这个阶段还可以访问修改前的props对象。

React兄弟、父子元素之间的通信的更多相关文章

  1. React 学习(六) ---- 父子组件之间的通信

    当有多个组件需要共享状态的时候,这就需要把状态放到这些组件共有的父组件中,相应地,这些组件就变成了子组件,从而涉及到父子组件之间的通信.父组件通过props 给子组件传递数据,子组件则是通过调用父组件 ...

  2. 【转】vue父子组件之间的通信

    vue父子组件之间的通信 在vue组件通信中其中最常见通信方式就是父子组件之中的通性,而父子组件的设定方式在不同情况下又各有不同.最常见的就是父组件为控制组件子组件为视图组件.父组件传递数据给子组件使 ...

  3. React中父子组件间的通信问题

    1.https://blog.csdn.net/sinat_17775997/article/details/59103173 (React中父子组件间的通信问题)

  4. vue的父子组建之间的通信(-),基于props和$emit之间的传递

    对于vue而言,以为其核心思想为前端组建化.所以组建之间的通信必不可少. 相信接触过Angularjs的童鞋都知道angularjs的控制器之间的通信机制. 1:父传子:官方的$broadcast() ...

  5. React之父子组件之间传值

    1.新增知识点 /** React中的组件: 解决html 标签构建应用的不足. 使用组件的好处:把公共的功能单独抽离成一个文件作为一个组件,哪里里使用哪里引入. 父子组件:组件的相互调用中,我们把调 ...

  6. React native和原生之间的通信

    RN中文网关于原生模块(Android)的介绍可以看到,RN前端与原生模块之 间通信,主要有三种方法: 1)使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript. 2)使 ...

  7. vue2.0 父子组件之间的通信问题

    概要: 父组件向子组件通信:props属性 子组件向父组件通信:$emit()触发事件,$on()监听事件 在 vue 1.0 中可以使用$dispatch 和 $broadcast来实现 向上派发事 ...

  8. vue非父子组件之间的通信

    https://www.cnblogs.com/chengduxiaoc/p/7099552.html   //vm.$emit( event, arg ) //触发当前实例上的事件 //vm.$on ...

  9. Phaser游戏框架与HTML Dom元素之间的通信交互

    本想按照PHASER的HTML Dom元素官方实例:http://labs.phaser.io/index.html?dir=game%20objects/dom%20element/&q=  ...

随机推荐

  1. WCF中记录SOAP消息日志

    Windows Communication Foundation (WCF) 默认启用消息日志,WCF使用了在System.Diagnostics名称空间中定义的跟踪机制.在这个跟踪机制中,通过在配置 ...

  2. 安装SQL Server For Linux(Install SQL Server)

    SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图) 1.      安装SQL Server 官网安装指南:https://docs.microsoft.com ...

  3. Adobe Photoshop for Mac(图像处理软件)破解版安装

    1.软件简介    Adobe Photoshop(简称 "PS")是 macOS 系统上一款由 Adobe Systems 开发和发行的图像处理软件.Photoshop 主要处理 ...

  4. 那天有个小孩教我WCF[一][2/3]

    接着上次的继续讲吧 我们开始吧 9.创建数据库 use master go --创建库 if exists(select * from sysdatabases where name='NewsDB' ...

  5. Android UI系列-----LinearLayout的综合使用

    这里将会对LinearLayout的布局方式进行一个综合的使用,通过一个例子来看看LinearLayout的嵌套布局方式,在这之前首先介绍三个属性: 1.①android:layout_weigth: ...

  6. (Java编程思想)Thinking in Java

    1. 为什么突然想去研读<Thinking in Java>? 最近终于下定决心撸了一本<Thinking in Java>第四版,虽然在此之前我就久闻这本书的大名,但一直未曾 ...

  7. default listener is not configured in grid infrastructure home

    Oracle Restart enable database creation requries Default listener configured and running in Grid Inf ...

  8. ADO.NET 数据库备份等操作

    public class SqlServerBackup { private string database; private string server; private string uid; p ...

  9. Git 标签操作

    允许有意义的名称到一个特定的版本库中的标签操作.Tom 决定标记他们的项目代码,以便他们以后可以更容易访问. 创建标签 让我们标记当前HEAD使用git tag命令.他提供的标记名称前加上-a选项,使 ...

  10. Java知多少(41)泛型详解

    我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数.小数和字符串,例如: x = 1 ...