二十、父组件向子组件传递信息
案例22:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .box{background:red;} </style> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> // 父组件 var Parent = React.createClass({ getInitialState: function () { return { checked: true, class:'box' }; }, render: function() { return ( <Child txt="是否喜欢咖啡" class={this.state.class} checked={this.state.checked} /> ); } }); // 子组件 var Child = React.createClass({ render: function () { var checked = this.props.checked; return ( <div className = {this.props.class}> {this.props.txt}: <input type="checkbox" checked={checked} /> </div> ); } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果图如下
分析如下
- 父元素Parent上在getInitialState里设置了两个初始值checked和class
- 父元素Parent的Child标签上有三个属性txt、class、checked。txt的属性值为“是否喜欢咖啡”;class的属性值是从getInitialState里获取的class的初始值,值为box;checked的属性值是从getInitialState里获取的checked的初始值,值为true。
- 子组件Child的checked这个变量的值,是从父组件Parent传递过来的,即为父组件Parent的Child标签上checked的属性值,即为true。
- 子组件Child的className的属性值,是从父组件Parent传递过来的,即为父组件Parent的Child标签上class的属性值,即为box。
- 子组件this.props.txt,是从父组件Parent传递过来的,即为父组件Parent的Child标签上txt的属性值,即为“是否喜欢咖啡”。
上面这个例子是父组件里面嵌套了一个子组件,当然我们子组件里面还可以嵌套孙子组件
案例23:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> // 父组件 var Parent = React.createClass({ getInitialState: function () { return { checked: true, }; }, render: function() { return ( <Child txt="是否喜欢咖啡" checked={this.state.checked} /> ); } }); // 子组件 var Child = React.createClass({ render: function () { return ( <div> <Grandchild txt={this.props.txt} /> <input type="checkbox" checked={this.props.checked} /> </div> ); } }); // 孙子组件 var Grandchild = React.createClass({ render: function () { return ( <label> {this.props.txt} </label> ); } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
分析如下
从这个例子我们可以知道,信息可以从Parent一直传递到Grandchild上去,以此类推可以依次传递下去。但是,如果组件嵌套层次太深,那么从外到内组件的交流成本就变得很高,通过 props 传递值的优势就不那么明显了。
二十一、子组件向父组件传值
案例24:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> // 父组件 var Parent = React.createClass({ getInitialState: function () { return { txt: 123 }; }, childChange: function (newState) { this.setState({ txt: newState }); }, render: function() { return ( <div> {this.state.txt} <Child tab="输入框" txt={this.state.txt} callback={this.childChange} /> </div> ); } }); // 子组件 var Child = React.createClass({ getInitialState: function () { return { txt: this.props.txt }; }, toChange: function (event) { var newState = event.target.value; this.setState({ txt: newState }); this.props.callback(newState); }, render: function () { return ( <div> <span>{this.props.tab}</span> <input type="text" value={this.state.txt} onChange={this.toChange} /> </div> ); } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
分析如下(文字结合图片一起看)
- 父组件Parent的Child标签上txt属性的值,是从getInitialState里设置的txt的值,即为123
- 子组件Child的span标签里{this.props.tab},是获取的父元素Parent里传递过来的信息,即为父元素Parent的Child标签上tab属性的值,即为“输入框”。
- 子组件Child的input标签上value的值,是从getInitialState里设置的txt的值,这个txt的值为父元素Parent的Child标签上txt属性的值,即为123。
- 在子组件Child里,当input值发生改变的时候,就触发onChange事件,调用toChange方法。
- 在子组件Child的toChange方法里,event.target.value是input的value值,将input的value值赋值给newState这个变量;通过setState将txt的值修改为newState的值,即为input的value值;this.props.callback,这里向父元素的callback里传递了一个newState值,即为input的value值。
- 在父组件Parent的Child标签上,callback被触发后,会调用childChange方法,在这个方法里,通过setState将txt的值修改为子组件Child传递过来的newState值。
二十二、没有嵌套关系的组件之间传值
案例25:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <meta charset="utf-8"> <script src="https://npmcdn.com/react@15.3.1/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.1/dist/react-dom.min.js"></script> <script src="https://npmcdn.com/babel-core@5.8.38/browser.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> var Parent = React.createClass({ getInitialState: function() { return { txt: '123' }; }, childOneCb:function(newOne){ this.setState({ txt:newOne }) }, render: function () { return ( <div> <ChildOne txt={this.state.txt} cbOne={this.childOneCb} /> <ChildTwo txt={this.state.txt} /> </div> ); } }); var ChildOne = React.createClass({ getInitialState: function() { return { txt: this.props.txt }; }, inputChange:function(event){ this.setState({ txt:event.target.value }); this.props.cbOne(event.target.value); }, render: function() { return ( <div> ChildOne:<input type="text" value={this.state.txt} onChange={this.inputChange} /> </div> ); } }); var ChildTwo = React.createClass({ render: function () { return ( <div> ChildTwo:{this.props.txt} </div> ); } }); ReactDOM.render( <Parent />, document.getElementById('example') ) </script> </body> </html>
效果如下
分析如下
- 首先来看父元素Parent
- 接下来看ChildOne
cbOne在父组件Parent上ChildOne标签上看到
- 接下来再回到父组件Parent上
这个时候已经完成了在子组件ChildOne上修改input的value值,父组件Parent里txt的状态会随之改变
- 下面来看ChildTwo
父组件Parent里txt值随着子组件ChildOne里input值而改变,这里的值也是获取的父组件Parent里txt的状态。因此ChildTwo里的值也会随着ChildOne里的值而改变。