当前位置:首页 > 系统运维

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/><span                             className="glyphicon glyphicon-chevron-up"></span></button>                     </div>                     <span>&ensp;</span>                     <div className="col-md-12">                         <button className="btn col-md-12" onClick={ this.decreateHandle}><span                             className="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之类的其他框架,等研究出来单独写篇文章吧

分享到:

滇ICP备2023006006号-16