ReactJS组件之间通信

2024-03-25 09:20
文章标签 组件 通信 之间 reactjs

本文主要是介绍ReactJS组件之间通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在学习react.js,不得不说第一次接触组件化开发很神奇,当然也很不习惯。
react的思想还是蛮独特的,当然围绕react的一系列自动化工具也是让我感觉亚历山大
今天总结一下react组件之间的通信,权当是自己的学习笔记:

reactJs中数据流向的的特点是:单项数据流

react组件之间的组合不知道为什么给我一种数据结构当中树的感觉,数据就是从根节点(顶端或其他子树的顶端)“流”下来,大概就是这个样子:
图片描述

比如这是一个组件树,数据就可以从main组件流到jumbotron组件、queationList组件、form组件,类似的queation组件的数据也可以流到下边的question组件里边。

但是很遗憾,这个从上到下的数据流动,只能解决很少的问题,还有一部分的数据流动就是类似从jumbotron组件到form组件的这样的兄弟组件的流动形式,或者隔着几个层级的数据流动,再或者子组件发生了数据的变化,想通知父组件,数据流向从子组件到父组件流,这些问题才是大多数的开发者需要面临的问题。
所以这篇笔记总结下基础的组件通信:

数据从父组件到子组件

图片描述

最简单的通信就是父子间的通信,比如上边图上的有个jsonObj从main流进了QueationList
参考代码:

//这里模拟出几条数据
var jsonObj=[{name:"A",question:"从小被人打怎么办?",TextArea:"习惯就好了",applaud:35,disagree:1},{name:"B",question:"长的太帅被人砍怎么办?",TextArea:"食屎啦你",applaud:35,disagree:10},{name:"C",question:"因为太胖被人摸怎么办?",TextArea:"享受就好了",applaud:35,disagree:45},{name:"D",question:"被老师打不开心",TextArea:"用钱打脸",applaud:35,disagree:6},{name:"E",question:"不爱洗澡怎么办?",TextArea:"打一顿就好了",applaud:35,disagree:9}
]var QuestionList=React.createClass({prepareToRender:function(list){var array=[];for(var i=0;i<list.length;i++){array.push(<Question obj={list[i]}   key={i}/>);}return array;},render:function(){var array=this.prepareToRender(this.props.jsonObj);return <div>{array}</div>;}
});
var Main = React.createClass({//开始渲染render: function () {return (<div><div className="container col-md-6 col-md-offset-3"><div className="container-fluid"><QuestionList jsonObj={jsonObj}  /></div></div>);}
});
ReactDOM.render(<Main />,document.getElementById('container')
);

代码写的不怎么规范,但是数据的传递就是这样的:
<QuestionList jsonObj={jsonObj} />
这样就可以把父组件的数据带到子组件里边

数据从子组件到父组件

理论上来说数据只能是单向的,所以不借助插件数据还真不好从子组件到父组件,一种很简单的手段是回调函数:
在父组件当中写个回调函数,然后传递到子组件,什么时候子组件数据变化了,直接调这个回调函数就可以了。
图片描述

比如现在的jumbotron的按钮被点击了,我们想把被点击这个事件发给它的父组件也就是main组件,那么我们可以这个做:

var Jumbotron = React.createClass({handleClick: function () {this.props.openTheWindow(false);},render: function () {return (<div className="row"><div className="col-md-6  col-md-offset-3"><button type="button" className="btn btn-default btn-lg" onClick={this.handleClick}>开始体验</button></div></div></div>);}
});var Main = React.createClass({getInitialState: function () {return {openTheWindow: true};},//开始给子组件一个回调函数,用来做子组件给父组件通信使用buttonResponse:function(windowSatus){this.setState({openTheWindow : windowSatus});},//开始渲染render: function () {console.log(jsonObj)return (<div><Jumbotron openTheWindow={this.buttonResponse}/></div>);}
});
ReactDOM.render(<Main />,document.getElementById('container')
);

子组件通知父组件状态变化就是这样,就好像是儿子找爸爸要零花钱,零花钱以及给不给都是爸爸说了算的。

兄弟组件之间的通信

这个其实应该是一个动态应用中最常见的通信,比如jubotron组件的点击按钮,form组件的表单出现:
这就是一个典型的兄弟之间的通信:
图片描述

兄弟节点其实可以就是子父通信&&父子通信的叠加
首先按钮被点击,子组件通知负组件这个事件,然后父组件把这个消息带给另一个子组件
下边是个点击按钮显示表单的例子:

/*** Created by niuGuangzhe on 2016/9/10.*/
var Jumbotron = React.createClass({handleClick: function () {this.props.openTheWindow(false);},render: function () {return (<div className="jumbotron"><div className="row"><div className="col-md-6  col-md-offset-3"><button type="button" className="btn btn-default btn-lg" onClick={this.handleClick}>开始体验</button></div></div></div>);}
});var Form = React.createClass({getInitialState:function(){return {inputTitle:"请输入标题",mainBody:"在此输入正文"};},//点击按钮触发事件:清除所有已经输入的文字cleanText:function(){this.setState({inputTitle:"",mainBody:""});},//表单监视事件handleChange(name,e) {var newState = {};console.log(name);newState[name] =event.target.value;this.setState(newState);},render: function () {return (<div style={{display:this.props.openTheWindow?"none":"block"}}><form role="form"><div className="form-group"><label htmlFor="title">标题</label><input type="text" className="form-control" id="title" name="inputTitle" value={this.state.inputTitle} onChange={this.handleChange.bind(this,"inputTitle")}/></div><div className="form-group"><label htmlFor="textArea">正文</label><textarea className="form-control" rows="3" id="textArea" name="mainBody" value={this.state.mainBody} onChange={this.handleChange.bind(this,"mainBody")}></textarea></div><div className="row"><input type="button" className="btn btn-default pull-right leaveMeAlone" value="取消"  onClick={this.cleanText}/><input type="submit" className="btn btn-primary pull-right leaveMeAlone" value="提交"/></div></form></div>)}
})var Main = React.createClass({getInitialState: function () {return {openTheWindow: true};},//开始给子组件一个回调函数,用来做子组件给父组件通信使用buttonResponse:function(windowSatus){this.setState({openTheWindow : windowSatus});},//开始渲染render: function () {console.log(jsonObj)return (<div><Jumbotron openTheWindow={this.buttonResponse}/><div className="container col-md-6 col-md-offset-3"><Form openTheWindow={this.state.openTheWindow}/></div></div>);}
});
ReactDOM.render(<Main />,document.getElementById('container')
);

就是这样,

其实上边的代码是我从之前的没事干做的一个单页面上拿过来改的,为了不出现代码无法运行的问题,下边贴出所有代码:

/*** Created by niuGuangzhe on 2016/9/10.*/
var Jumbotron = React.createClass({handleClick: function () {this.props.openTheWindow(false);},render: function () {return (<div className="jumbotron"><div className="row"><div className="col-md-6  col-md-offset-3"><h2 className="colorChange">React+bootstrap简单实例</h2></div></div><div className="row"><div className="col-md-6  col-md-offset-3"><p className="colorChange">上手体验:第一次尝试组件化开发</p></div></div><div className="row"><div className="col-md-6  col-md-offset-3"><button type="button" className="btn btn-default btn-lg" onClick={this.handleClick}>开始体验</button></div></div></div>);}
});var Form = React.createClass({getInitialState:function(){return {inputTitle:"请输入标题",mainBody:"在此输入正文"};},//点击按钮触发事件:清除所有已经输入的文字cleanText:function(){this.setState({inputTitle:"",mainBody:""});},//表单监视事件handleChange(name,e) {var newState = {};console.log(name);newState[name] =event.target.value;this.setState(newState);},render: function () {return (<div style={{display:this.props.openTheWindow?"none":"block"}}><form role="form"><div className="form-group"><label htmlFor="title">标题</label><input type="text" className="form-control" id="title" name="inputTitle" value={this.state.inputTitle} onChange={this.handleChange.bind(this,"inputTitle")}/></div><div className="form-group"><label htmlFor="textArea">标题</label><textarea className="form-control" rows="3" id="textArea" name="mainBody" value={this.state.mainBody} onChange={this.handleChange.bind(this,"mainBody")}></textarea></div><div className="row"><input type="button" className="btn btn-default pull-right leaveMeAlone" value="取消"  onClick={this.cleanText}/><input type="submit" className="btn btn-primary pull-right leaveMeAlone" value="提交"/></div></form></div>)},//监测从新渲染componentDidUpdate:function(){console.log("子组件重新渲染;");}
})var Question = React.createClass({getInitialState : function(){return {click:true,disClick:true};},numberHandle:function(){if(this.state.click===true){//奇数次点击,开始增加数据this.props.obj.applaud+=1;this.setState({click:false});}else{//偶数次点击,减去数据this.props.obj.applaud-=1;this.setState({click:true});}},decreateHandle:function(){if(this.state.disClick===true){//奇数次点击,开始增加数据this.props.obj.applaud-=1;this.setState({disClick:false});}else{//偶数次点击,减去数据this.props.obj.applaud+=1;this.setState({disClick:true});}},render: function () {return (<div className="row leaveMe"><div className="col-md-2"><div className="col-md-12"><button className="btn col-md-12 " onClick={this.numberHandle}>{this.props.obj.applaud-this.props.obj.disagree}<br/><spanclassName="glyphicon glyphicon-chevron-up"></span></button></div><span>&ensp;</span><div className="col-md-12"><button className="btn col-md-12" onClick={this.decreateHandle}><spanclassName="glyphicon glyphicon-chevron-down"></span></button></div></div><div className="col-md-10  bs-callout bs-callout-info"><h4>{this.props.obj.question}</h4><p>{this.props.obj.TextArea}</p></div></div>);}
});var QuestionList=React.createClass({prepareToRender:function(list){var array=[];for(var i=0;i<list.length;i++){array.push(<Question obj={list[i]}   key={i}/>);}return array;},render:function(){var array=this.prepareToRender(this.props.jsonObj);return <div>{array}</div>;}
});//这里模拟出几条数据
var jsonObj=[{name:"A",question:"从小被人打怎么办?",TextArea:"习惯就好了",applaud:35,disagree:1},{name:"B",question:"长的太帅被人砍怎么办?",TextArea:"食屎啦你",applaud:35,disagree:10},{name:"C",question:"因为太胖被人摸奶怎么办?",TextArea:"享受就好了",applaud:35,disagree:45},{name:"D",question:"被老师打不开心",TextArea:"用钱打ta脸",applaud:35,disagree:6},{name:"E",question:"不爱洗澡怎么办?",TextArea:"打一顿就好了",applaud:35,disagree:9}
]var Main = React.createClass({getInitialState: function () {return {openTheWindow: true};},//开始给子组件一个回调函数,用来做子组件给父组件通信使用buttonResponse:function(windowSatus){this.setState({openTheWindow : windowSatus});},//开始渲染render: function () {console.log(jsonObj)return (<div><Jumbotron openTheWindow={this.buttonResponse}/><div className="container col-md-6 col-md-offset-3"><Form openTheWindow={this.state.openTheWindow}/><br/><br/><div className="container-fluid"><QuestionList jsonObj={jsonObj}  /></div></div></div>);},
//    执行hook函数:重新渲染完成的时候调这个函数componentDidUpdate:function(){console.log(this.state.openTheWindow);}
});
ReactDOM.render(<Main />,document.getElementById('container')
);

最后就是一个很重要的问题:就是多层级的据数据传输,如果还用这个方式来传播的话,效率貌似是个大问题,解决办法看大家的做法目前暂时还是flux之类的其他框架,等研究出来单独写篇文章吧

这篇关于ReactJS组件之间通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/844552

相关文章

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

在Spring Boot中实现HTTPS加密通信及常见问题排查

《在SpringBoot中实现HTTPS加密通信及常见问题排查》HTTPS是HTTP的安全版本,通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护,下面通过本文给大家介绍在SpringB... 目录一、HTTPS核心原理1.加密流程概述2.加密技术组合二、证书体系详解1、证书类型对比2. 证书获

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

基于C#实现MQTT通信实战

《基于C#实现MQTT通信实战》MQTT消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点,下面我们就来看看C#实现... 目录1、连接主机2、订阅消息3、发布消息MQTT(Message Queueing Telemetr

PyQt6中QMainWindow组件的使用详解

《PyQt6中QMainWindow组件的使用详解》QMainWindow是PyQt6中用于构建桌面应用程序的基础组件,本文主要介绍了PyQt6中QMainWindow组件的使用,具有一定的参考价值,... 目录1. QMainWindow 组php件概述2. 使用 QMainWindow3. QMainW

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J